Win RT Metro C#MVVM从工作线程更新UI

0xD*_*EEF 1 user-interface multithreading mvvm microsoft-metro windows-runtime

我有工人阶级

public event EventHandler<EventArgs> DataModified;
Run Code Online (Sandbox Code Playgroud)

可以从UI线程之外引出(它是从服务器获取更新的网络客户端).我有ModelView

ObservableCollection<DataModel> DataItems;
Run Code Online (Sandbox Code Playgroud)

视图绑定到哪个.我的modelview必须订阅ModifiedEvent,因此它可以反映DataItems中的更改.如何从回调事件更新DataItems?我无法从模型视图访问UI Dispatcher(因为视图不应该知道模型视图).什么是正确的.NET 4.5方式来处理这个?

Ant*_*kov 6

您可以创建一个服务,它可以保存CoreDispatcher并注入您的视图模型(或使其静态)

public static class SmartDispatcher
{
    private static CoreDispatcher _instance;
    private static void RequireInstance()
    {
        try
        {
            _instance = Window.Current.CoreWindow.Dispatcher;

        }
        catch (Exception e)
        {
            throw new InvalidOperationException("The first time SmartDispatcher is used must be from a user interface thread. Consider having the application call Initialize, with or without an instance.", e);
        }

        if (_instance == null)
        {
            throw new InvalidOperationException("Unable to find a suitable Dispatcher instance.");
        }
    }

    public static void Initialize(CoreDispatcher dispatcher)  
    {
        if (dispatcher == null)
        {
            throw new ArgumentNullException("dispatcher");
        }

        _instance = dispatcher;
    }

    public static bool CheckAccess()
    {
        if (_instance == null)
        {
            RequireInstance();
        }
        return _instance.HasThreadAccess;
    }

    public static void BeginInvoke(Action a)
    {
        if (_instance == null)
        {
            RequireInstance();
        }

        // If the current thread is the user interface thread, skip the
        // dispatcher and directly invoke the Action.
        if (CheckAccess())
        {
            a();
        }
        else
        {
            _instance.RunAsync(CoreDispatcherPriority.Normal, () => { a(); });
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您应该在App.xaml.cs中初始化SmartDispatcher:

 var rootFrame = new Frame();
 SmartDispatcher.Initialize(rootFrame.Dispatcher);

 Window.Current.Content = rootFrame;
 Window.Current.Activate();
Run Code Online (Sandbox Code Playgroud)

以这种方式使用它:

SmartDispatcher.BeginInvoke(() => _collection.Add(item));
Run Code Online (Sandbox Code Playgroud)

本课程基于Jeff Wilcox的Windows Phone 7模拟.