执行数据库操作时无法在 WPF 中显示 GIF 加载程序
Not able display GIF loader in WPF While Database operation executing
您好,我正在尝试在执行某些耗时的操作时显示 GIf 图像。
我尝试使用以下代码..我能够看到负载 window 但 gif 图像的动画不工作.. 在搜索解决方案时我找到了更新 UI 的方法而它被冻结通过后台功能。但它仍然不起作用。这是我的装载机 Window XAML 代码:
<Window x:Class="project1.Views.loader"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:wfi="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
xmlns:winForms="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
xmlns:gif="http://wpfanimatedgif.codeplex.com"
gif:ImageBehavior.AnimateInDesignMode="True"
Title="Loading" Height="180" Width="461" WindowStartupLocation="CenterScreen" ResizeMode="NoResize" WindowStyle="SingleBorderWindow" Loaded="Window_Loaded">
<StackPanel Name="LoadingData" Background="White" >
<Label x:Name="lblprogressmessage" x:FieldModifier="public" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,35,0,10" Content="" Foreground="#FF1E8ED4" FontSize="14"></Label>
<Image x:Name="imggif" gif:ImageBehavior.RepeatBehavior="Forever" gif:ImageBehavior.AnimatedSource="pack://application:,,,/project1;component/Images/ajaxloader.gif" Height="50px" Width="60px"/>
</StackPanel>
</Window>
我正在尝试在另一个用户控件 window 中显示此 window,该控件具有按钮,单击此处时将执行一些数据库操作是我的按钮代码
loaderWindow ld = new loaderWindow // object to show loader window
Sample ViewModel = new Sample();
private void btn_Click(object sender, RoutedEventArgs e)
{
try
{
SampleEntityManager objem = new SampleEntityManager ();
using (var dbContext = Database1.getDBContext())
{
if(objem .checkFundExist(dbContext,Guid.Parse(cbx1SelectedValue.ToString()), Guid.Parse(cbx2.SelectedValue.ToString()), int.Parse(cbx3.SelectedValue.ToString())) == false)
{
BackgroundWorker bw = new BackgroundWorker();
bw.WorkerSupportsCancellation = true;
bw.WorkerReportsProgress = true;
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
ForceUIToUpdate();
bw.RunWorkerAsync();
ld.lblprogressmessage.Content = "Creating Fund for Year "+cbx1.Text +" Please Wait. . .";
*ld.Show();* // calling show method to display loader window
}
else
{
MessageBox.Show("Fund Has Already Been Created", "Info", MessageBoxButton.OK, MessageBoxImage.Information);
}
}
}
catch (Exception es)
{
MessageBox.Show("Invalid Opertaion try again.If Problem Persists Contact Support", "Error", MessageBoxButton.OK, MessageBoxImage.Information);
}
}
这是在冻结时强制更新 UI 的方法
// method to update UI
public static void ForceUIToUpdate()
{
DispatcherFrame frame = new DispatcherFrame();
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Render, new DispatcherOperationCallback(delegate (object parameter)
{
frame.Continue = false;
return null;
}), null);
Dispatcher.PushFrame(frame);
}
和后台工作代码如下
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
if ((worker.CancellationPending == true))
{
e.Cancel = true;
}
else
{
// Perform a time consuming operation and report progress.
this.Dispatcher.InvokeAsync((Action)(() =>
{
// Time Consuming Database method which will set Fund entry Field for all the employess in Union
ViewModel .CreateFund(cbx1.SelectedItem, cbx2.SelectedItem,cbx3.SelectedValue.ToString(), txt_desc.Text);
cbx1.SelectedIndex = -1;
cbx2.SelectedIndex = -1;
**ld.Hide();** // calling Hide Method close Loader window once database opertaion completed
}), System.Windows.Threading.DispatcherPriority.Background);
}
}
private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
BackgroundWorker worker = (BackgroundWorker)sender;
if ((e.Cancelled == true))
{
ld.lblprogressmessage.Content = "Cancelled !";
}
else if (!(e.Error == null))
{
ld.lblprogressmessage.Content = ("Error : " + e.Error.Message);
}
else
{
if (worker.WorkerSupportsCancellation == true)
{
worker.CancelAsync();
}
}
}
请建议我完成任务的方法。谢谢
您使用的 BackgroundWorker
有误。您从 DoWork
方法调用 Dispatcher.InvokeAsync
,该方法实际上是在 UI 线程而不是后台线程上执行代码,因此阻塞了 UI。您需要做的是找到一种方法在后台实际执行您的耗时代码,然后在工作完成后仅从 RunWorkerCompleted
更新 UI,或者使用 ReportProgress
如果您需要在执行期间更新 UI。
How to: Use a Background Worker
此外,在您启动 worker 时显示加载器 window,就像您已经做的那样,但是调用方法将其隐藏在 RunWorkerCompleted
中,它正在 [=24] 上执行=] 背景线程完成后的线程,而不是来自 DoWork
方法。
您好,我正在尝试在执行某些耗时的操作时显示 GIf 图像。
我尝试使用以下代码..我能够看到负载 window 但 gif 图像的动画不工作.. 在搜索解决方案时我找到了更新 UI 的方法而它被冻结通过后台功能。但它仍然不起作用。这是我的装载机 Window XAML 代码:
<Window x:Class="project1.Views.loader"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:wfi="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
xmlns:winForms="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
xmlns:gif="http://wpfanimatedgif.codeplex.com"
gif:ImageBehavior.AnimateInDesignMode="True"
Title="Loading" Height="180" Width="461" WindowStartupLocation="CenterScreen" ResizeMode="NoResize" WindowStyle="SingleBorderWindow" Loaded="Window_Loaded">
<StackPanel Name="LoadingData" Background="White" >
<Label x:Name="lblprogressmessage" x:FieldModifier="public" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,35,0,10" Content="" Foreground="#FF1E8ED4" FontSize="14"></Label>
<Image x:Name="imggif" gif:ImageBehavior.RepeatBehavior="Forever" gif:ImageBehavior.AnimatedSource="pack://application:,,,/project1;component/Images/ajaxloader.gif" Height="50px" Width="60px"/>
</StackPanel>
</Window>
我正在尝试在另一个用户控件 window 中显示此 window,该控件具有按钮,单击此处时将执行一些数据库操作是我的按钮代码
loaderWindow ld = new loaderWindow // object to show loader window
Sample ViewModel = new Sample();
private void btn_Click(object sender, RoutedEventArgs e)
{
try
{
SampleEntityManager objem = new SampleEntityManager ();
using (var dbContext = Database1.getDBContext())
{
if(objem .checkFundExist(dbContext,Guid.Parse(cbx1SelectedValue.ToString()), Guid.Parse(cbx2.SelectedValue.ToString()), int.Parse(cbx3.SelectedValue.ToString())) == false)
{
BackgroundWorker bw = new BackgroundWorker();
bw.WorkerSupportsCancellation = true;
bw.WorkerReportsProgress = true;
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
ForceUIToUpdate();
bw.RunWorkerAsync();
ld.lblprogressmessage.Content = "Creating Fund for Year "+cbx1.Text +" Please Wait. . .";
*ld.Show();* // calling show method to display loader window
}
else
{
MessageBox.Show("Fund Has Already Been Created", "Info", MessageBoxButton.OK, MessageBoxImage.Information);
}
}
}
catch (Exception es)
{
MessageBox.Show("Invalid Opertaion try again.If Problem Persists Contact Support", "Error", MessageBoxButton.OK, MessageBoxImage.Information);
}
}
这是在冻结时强制更新 UI 的方法
// method to update UI
public static void ForceUIToUpdate()
{
DispatcherFrame frame = new DispatcherFrame();
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Render, new DispatcherOperationCallback(delegate (object parameter)
{
frame.Continue = false;
return null;
}), null);
Dispatcher.PushFrame(frame);
}
和后台工作代码如下
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
if ((worker.CancellationPending == true))
{
e.Cancel = true;
}
else
{
// Perform a time consuming operation and report progress.
this.Dispatcher.InvokeAsync((Action)(() =>
{
// Time Consuming Database method which will set Fund entry Field for all the employess in Union
ViewModel .CreateFund(cbx1.SelectedItem, cbx2.SelectedItem,cbx3.SelectedValue.ToString(), txt_desc.Text);
cbx1.SelectedIndex = -1;
cbx2.SelectedIndex = -1;
**ld.Hide();** // calling Hide Method close Loader window once database opertaion completed
}), System.Windows.Threading.DispatcherPriority.Background);
}
}
private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
BackgroundWorker worker = (BackgroundWorker)sender;
if ((e.Cancelled == true))
{
ld.lblprogressmessage.Content = "Cancelled !";
}
else if (!(e.Error == null))
{
ld.lblprogressmessage.Content = ("Error : " + e.Error.Message);
}
else
{
if (worker.WorkerSupportsCancellation == true)
{
worker.CancelAsync();
}
}
}
请建议我完成任务的方法。谢谢
您使用的 BackgroundWorker
有误。您从 DoWork
方法调用 Dispatcher.InvokeAsync
,该方法实际上是在 UI 线程而不是后台线程上执行代码,因此阻塞了 UI。您需要做的是找到一种方法在后台实际执行您的耗时代码,然后在工作完成后仅从 RunWorkerCompleted
更新 UI,或者使用 ReportProgress
如果您需要在执行期间更新 UI。
How to: Use a Background Worker
此外,在您启动 worker 时显示加载器 window,就像您已经做的那样,但是调用方法将其隐藏在 RunWorkerCompleted
中,它正在 [=24] 上执行=] 背景线程完成后的线程,而不是来自 DoWork
方法。