在公共库上创建BaseViewModel

时间:2017-11-17 16:22:55

标签: wpf mvvm

我有一个需要在我的主WPF应用程序及其插件之间共享的公共库... 在公共库中,我有一个带有此代码的BaseViewModel

    public Dispatcher RootDispatcher
    {
        get
        {
            _rootDispatcher = _rootDispatcher ??
                (App.Current != null
                    ? App.Current.Dispatcher
                    : Dispatcher.CurrentDispatcher);
            return _rootDispatcher;
        }
        // unit tests can get access to this via InternalsVisibleTo
        internal set
        {
            _rootDispatcher = value;
        }
    }

    protected void TriggerSafeEvent(EventHandler eve, EventArgs args)
    {
        if (RootDispatcher.CheckAccess())
        {
            if (eve != null)
                eve.Invoke(this, args);
        }
        else
        {
            RootDispatcher.Invoke((Action)delegate()
            {
                if (eve != null)
                    eve.Invoke(this, args);
            });
        }
    }

因此,消费者ViewModel可以以这样的方式调用事件,而不必担心线程属于主线程的任何地方:

    MyViewModel : BaseViewModel {

    ..
            TriggerSafeEvent(MyEventHandler, MyEventArgs);

    }

由于公共库不是WPF应用程序,因此不会解析App对象。

我认为这种方法可能是错误的,但我觉得在基本视图模型中经常调用方法并不是一种不常见的做法。

使用 App 对象处理的最佳解决方案是什么?

1 个答案:

答案 0 :(得分:2)

使用依赖注入。这不是我的头脑,但它会起作用。

public interface IDispatcherProvider {
    Dispatcher Dispatcher { get; }
}

BaseViewModel

public static IDispatcherProvider DispatcherProvider { get; set; }

接口实现:

public class DispatcherProviderImplementation : IDispatcherProvider
{
    public DispatcherProviderImplementation(Func<Dispatcher> getDispatcher)
    {
        _getDispatcher = getDispatcher;
    }

    private Func<Dispatcher> _getDispatcher;

    public virtual Dispatcher Dispatcher => _getDispatcher?.Invoke();

    //  If your compiler won't accept the above, try this
    /*
    public virtual Dispatcher Dispatcher {
        get {
            return (_getDispatcher == null) ? null : _getDispatcher();
        }
    }
    */
}

应用

    static App()
    {
        BaseViewModel.DispatcherProvider 
            = new DispatcherProviderImplementation(() => (App.Current != null
                ? App.Current.Dispatcher
                : Dispatcher.CurrentDispatcher));
    }