如何在将项目绑定到组合框时在WPF MVVM中使用调度程序 [英] How to use dispatcher in WPF MVVM while binding items to the combobox

查看:91
本文介绍了如何在将项目绑定到组合框时在WPF MVVM中使用调度程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述





我在WPF MVVM中实现一个应用程序。



我有WPF应用程序和DLL类库。



例如在应用程序中我有2个组合框



我有约束力数据库服务器到第一个组合框。



基于第一个组合框选择然后我将第二个组合框与所有数据库的列表绑定。



我的问题在于,当我们从第一个组合框中选择服务器时,它保持打开状态,应用程序会挂起一段时间。我无法在该特定时间进行其他操作。



我的XAML代码如下:

Hi,

I am implementing one application in WPF MVVM.

I am having WPF application and DLL class library.

For example in application I am having 2 combobox's

I am binding database servers to the 1st combobox.

based on the 1st combobox selection then I am binding the 2nd combobox with list of all the databases.

my problem is here when we select the server from the 1st combobox it keep open state and Application gets hangs some time. I am unable to do other operations at that particular time.

My XAML code below :

<ComboBox Grid.Column="2" 
                  Grid.Row="1" Grid.ColumnSpan="3" MaxHeight="25" 
                  ItemsSource="{Binding Servers}"  
                  SelectedValue="{Binding SelectedServer}"
                  Name="cboServer" 
                  DataContext="{Binding Source={StaticResource vm}}" />

<ComboBox Grid.Column="2" 
             Grid.Row="2" Grid.ColumnSpan="3" MaxHeight="25" 
             ItemsSource="{Binding Databases}"
             SelectedValue="{Binding SelectedDatabase}"
             Name="cboDatabase" 
             DataContext="{Binding Source={StaticResource vm}}"/>



我的模型代码如下:


My view model code as follows:

/// <summary>
        /// For Servers Properties
        /// </summary>
        private ObservableCollection<string> _Servers;         
        private string _SelectedServer;
        public ObservableCollection<string> Servers        
        {
            get { return _Servers; }
            set
            {
                _Servers = value;
                OnPropertyChanged("Servers");
            }
        }
        public string SelectedServer
        {
            get { return _SelectedServer; }
            set
            {
               _SelectedServer = value;
                OnPropertyChanged("SelectedServer");

_extractInfo.ServerName = !string.IsNullOrEmpty(_SelectedServer) ? _SelectedServer : null;
         if (!string.IsNullOrEmpty(_extractInfo.ServerName))
              GetDatabases();
           else
              Databases = new ObservableCollection<string>();

}
}

         /// <summary>
        /// For Databases 
        /// </summary>
        private ObservableCollection<string> _DataBaseList; 
        private string _SelectedDatabase;
        public ObservableCollection<string> Databases         
        {
            get { return _DataBaseList; }
            set
            {
                _DataBaseList = value;
                           
                OnPropertyChanged("Databases");
            }
        }

//calling function GetDatabases(): ExtractHelper is located in my DAL Project
private ObservableCollection<string> GetDatabases()
        {
           try
            {
               
             Databases = new ObservableCollection<string>(ExtractHelper.RequestList(_extractInfo, ExtractHelper.RequestTypes.Databases).AsEnumerable().Select(x => x.DatabaseName));
                
                return Databases;
            }
            catch(Exception ex)
            { 
                MessageBox.Show(ex.Message);
            }
            return null;
        }



请告诉我代码是否有任何问题,如果错误让我知道我们如何实现而不冻结应用程序



我尝试了什么:



我尝试过使用Dispatcher,如下所示。

当我使用下面的代码时,第一个组合框在我选择服务器时关闭,但是应用程序会冻结一段时间,然后在第二个组合框中显示数据库列表。


Kindly let me know is there any wrong with the code, if its wrong let me know how we achieve without freeze the application

What I have tried:

I have tried using Dispatcher like below.
When I am using below code, 1st combobox gets closed when I select the server, but application gets freezes some time then its displaying the databases list in the 2nd combobox.

public string SelectedServer
        {
            get { return _SelectedServer; }
            set
            {
               _SelectedServer = value;
                OnPropertyChanged("SelectedServer");

                _extractInfo.ServerName = !string.IsNullOrEmpty(_SelectedServer) ? _SelectedServer : null;
                
                if (!string.IsNullOrEmpty(_extractInfo.ServerName))
                    
                Application.Current.Dispatcher.BeginInvoke(
                    new Action(() =>
                    {

                     GetDatabases();
                        
                    }),
                    DispatcherPriority.Background,
                    null
                );
                    
                else
                    
                   Databases = new ObservableCollection<string>();
                 }
        }

推荐答案



我想你需要时间更新数据库列表。

你可以使用后台工作者来更新这个列表。

我将使用这个场景:

- 删除列表选择服务器并禁用数据库控制后的数据库

- 启动后台工作程序以获取将在已完成的事件中作为参数发送的新列表

- 在已完成的事件处理设置新的数据库列表并启用控件。



祝你好运
Hi,
I think you take time to update the list of databases.
You can use a backgroundworker to update this list.
I will use this scenario:
- delete the list of databases after selection of server and disable the control of database
- launch the backgroundworker to get the new list that will be send as parameter in the completed event
- In the completed event handling set the new data base list and enable the control.

Best regards


Async...await TPL框架 [ ^ ]就是答案。在另一个线程上关闭任务以释放UI线程并阻止它冻结。



多线程程序需要投入学习。在做任何工作之前,最好先查看TPL专家的以下资源:



* 异步和等待简介 [ ^ ] - Stephen Cleary(他博客上有很多或有用的信息)



* 异步编程揭秘 - YouTube [ ^ ]作者Stephen Cleary



* C#和Visual Basic的异步最佳实践 - YouTube [ ^ ]来自 Mads Torgersen [ ^ ] - Microsoft的首席语言架构师。这使用了一个问题&解决方法 - 非常有用!
Async...await TPL framework[^] is the answer. Spin a task off on another thread to release the UI thread and stop it from freezing.

Multithreaded program is something that needs a n investment in learning. Best to check out the following resources from the TPL gurus before doing any work:

* Async and Await Introduction[^] - Stephen Cleary (a lot or helpful information on his blog)

* Asynchronous Programming Demystified - YouTube[^] by Stephen Cleary

* Async Best Practices for C# and Visual Basic - YouTube[^] by Mads Torgersen[^] - Chief language architect at Microsoft. This uses a problem & solution approach - very helpful!


如果您使用的是.NET 4.5及更高版本,我建议您利用这些新功能将ObservableCollection从调度程序中移除。基本上,您希望从以下内容开始:
If you are using .NET 4.5 and above, I would recommend that you take advantage of the new features for moving the ObservableCollection off the dispatcher. Basically, you want to start off with something like this:
public class MyViewModel
{
  private readonly object _lock = new object();
  public ObservableCollection<string> Servers { get; private set; }
  public MyViewModel()
  {
    _servers = new ObservableCollection<string>();
    BindingOperations.EnableCollectionSynchronization(Servers, _lock);
  }

  public async void UpdateServers()
  {
    await Task.Run(()=>
      {
        MySlowService slowService = new MySlowService();
        string[] servers = await slowService.GetSlowOperation();
        foreach (string server in servers)
        {
          Servers.Add(server);
        }
      });
  }
}

请注意,这只是向您展示如何组合这些技术的示例;你将不得不做的工作将其整合到你的解决方案中。

Please note, this is just an example to show you how to combine these techniques; you're going to have to do work to integrate this into your solution.


这篇关于如何在将项目绑定到组合框时在WPF MVVM中使用调度程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆