如何将View中的控件的UI调度程序传递给ViewModel

时间:2013-08-30 12:04:11

标签: wpf silverlight mvvm mvvm-light

有一个类似的问题(How to pass the UI Dispatcher to the ViewModel 任何人都提供了一些示例或完整的代码。我是MVVM的新手,所以我没有得到。

private async void BindMatchGridinAsync()
        {
            await BindMatchGridAsync(); 
        }        
        async Task<ObservableCollection<EfesBet.DataContract.GetMatchDetailsDC>> BindMatchGridAsync()
        {
            await Task.Run(() => 
                {
                    BindMatchGrid();
                });
            return null;
        }
        void BindMatchGrid()
        {
            BindMatchGridDel bindDel = new BindMatchGridDel(BindMatchGridData);
            matchList = new List<GetMatchDetailsDC>();            
            matchList = proxy.GetMatch().ToList();            
            dataGridParent.Dispatcher.BeginInvoke(bindDel, null);
        }
        public delegate void BindMatchGridDel();
        void BindMatchGridData()
        {
            dataGridParent.ItemsSource = matchList;
        }

现在在这段代码中BindMatchGridinAsync()我把我的代码构造函数放在文件后面(.cs文件)。它正在进行适当的异步操作。但我需要在ViewModel中实现相同的功能。请建议我如何实现它。 提前感谢你。

5 个答案:

答案 0 :(得分:2)

你正在考虑像WinForms开发人员那样,每个控件都可以在一个单独的线程上。

在WPF中有一个UI线程。该线程称为Dispatcher。因此,每个控件都将使用相同的调度程序。

如上所述:

Application.Current.Dispatcher.BeginInvoke(new Action(DoSomething),null);

完全可以接受,并且可以与所有控件一起使用,因为所有控件都使用应用程序Dispatcher。

答案 1 :(得分:0)

您不需要在ViewModel中传递调度程序(WPF版本):

Application.Current.Dispatcher.BeginInvoke(new Action(DoSomething),null);

答案 2 :(得分:0)

使用MVVM Light,您可以使用DispatcherHelper静态类:

// Get the UI dispatcher :
var uiDispatcher = DispatcherHelper.UIDispatcher;
// Execute in UI :
// In current thread
DispatcherHelper.CheckBeginInvokeOnUI(() =>
{
    // In UI thread
});

答案 3 :(得分:0)

最佳解决方案是以不需要调度程序的方式使用asyncawait

async Task<ObservableCollection<GetMatchDetailsDC>> BindMatchGridAsync()
{
    var matchList = await Task.Run(() => BindMatchGrid());
    dataGridParent.ItemsSource = matchList;
    return new ObservableCollection<GetMatchDetailsDC>(matchList);
}

List<GetMatchDetailsDC> BindMatchGrid()
{
    matchList = new List<GetMatchDetailsDC>();            
    matchList = proxy.GetMatch().ToList();            
    return matchList;
}

答案 4 :(得分:0)

不要这样做!使用MVVM的重点是将UI实现与应用程序逻辑分开。如果您将静态调用推送到Application.Current.Dispatcher或类似,则会立即将您的视图模型绑定到WPF实现。如何在隔离WPF的情况下测试视图模型?

如果你真的想要静态访问UI线程,那么至少要使用一些东西来抽象你正在使用WPF的事实,比如SynchronizationContext

public class MyViewModel : NotificationObject
{
    private SynchronizationContext _context;

    public MyViewModel()
    {
        _context = SynchronizationContext.Current;
    }
}

假设在UI线程上调用构造函数,您现在有一个私有变量,它使您在调度程序上运行代码后门。

更好的是,您可以在IoC容器中注册SynchronizationContext.Current(或它的抽象),并在构造函数中注入它。那么你不依赖于UI线程构建视图模型这一事实。