【问题标题】:disabling a window禁用窗口
【发布时间】:2010-05-20 13:16:06
【问题描述】:

在我的应用程序中,我有一个Button。如果在执行对数据库的选择时单击该按钮,则结果将显示在ListView 中。 由于选择比较复杂,需要一些时间来检索数据。

当我单击Button 时,应禁用Application-Window,直到加载数据。 但是当我将窗口的IsEnabled-Property 设置为false 时,加载数据后窗口会被禁用。

我尝试使用BackgroundWorker 在另一个线程中禁用Window。但后来我得到一个异常,该窗口已被另一个线程使用。

如何在Window 检索数据之前禁用它?

【问题讨论】:

    标签: c# wpf multithreading window


    【解决方案1】:

    您在后台线程中做错了事。您必须从 UI 线程影响 UI,并且您的数据加载应该在后台线程中进行。

    最简单的方法是使用BackgroundWorker 来加载您的数据,将该数据存储在一个类级别的变量中,当您的后台工作是complete 时,UI 会重新启用并从该类加载数据级变量。

    【讨论】:

    • 感谢您的回答。我自己也想过这样做。不幸的是,由于应用程序的设计,这并不容易。所以我希望也许有人会有其他解决方案。
    【解决方案2】:

    我认为您应该将数据库活动移动到后台线程以使您的 UI 保持响应(即使只是禁用它),而不是相反。

    【讨论】:

      【解决方案3】:

      试试这个:

      BackgroundWorkerHelper.DoWork<Type of object you want to retrieve>(
                         () =>
                         {
                            //Load your data here
                            //Like
                              using (MarketingService svc = new MarketingService())
                              {
                                  return svc.GetEmployeeLookupTable();
                              }
                         },
                             (args) =>
                             {
                                 this.IsEnable = true;
                                 if (args.Error == null)
                                 {
                                     Your Target Datasource= args.Result;
                                 }
                             });
      
      this.IsEnable = false;
      

      【讨论】:

        【解决方案4】:

        除了后台线程,我会建议“BusyDialog”窗口。

        你的忙碌对话框可以是一个动画,显示它正在做某事,并以模态方式阻止任何用户输入。

        public partial class BusyDialog : Window
        {
            public BusyDialog()
            {
                InitializeComponent();
            }
        
            public static T Execute<T>(DependencyObject parent, Func<T> action)
            {
        
                Window parentWindow = null;
                if (parent is Window)
                {
                    parentWindow = parent as Window;
                }
                else
                {
                    parentWindow = Window.GetWindow(parent);
                }
        
                T val = default(T);
                Exception le = null;
                BusyDialog bd = new BusyDialog();
                bd.Owner = parentWindow;
                ThreadPool.QueueUserWorkItem((o) =>
                {
                    try
                    {
                        val = action();
                    }
                    catch (Exception ex)
                    {
                        le = ex;
                    }
                    bd.EndDialog();
                });
                bd.ShowDialog();
                if (le != null)
                {
                    Trace.WriteLine(le.ToString());
                    throw new Exception("Execute Exception", le);
                }
                return val;
            }
        
            private void EndDialog()
            {
                Dispatcher.Invoke((Action)delegate() {
                    this.DialogResult = true;
                });
            }
        
        }
        

        现在您可以使用以下方式异步调用您的方法,

        List<Result> results = BusyDialog.Execute( this , 
           ()=>{
               return MyLongDatabaseLoadingCall();
           });
        

        这就是发生的事情,

        1. BusyDialog 以模态方式显示,阻止任何用户输入并显示忙碌动画
        2. 在 ThreadPool.QueueUserItem 中执行对您的方法 MyLongDatabaseLoadingCall 的调用,该方法在不同的线程中异步调用您的方法(与此处其他人建议的后台线程功能相同)。
        3. 动画一直持续到调用执行为止
        4. 当您的方法结束时,BusyDialog 也将结束,一切都恢复原状。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-12-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-04-20
          • 2012-09-17
          • 2018-06-11
          • 1970-01-01
          相关资源
          最近更新 更多