Fabrizio Stellato
Fabrizio Stellato

Reputation: 1891

Create a BaseViewModel on a common library

I have a common library that need to be shared among my main WPF app and its plugins... In the common library I have a BaseViewModel with this code

    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);
            });
        }
    }

So the consumer ViewModel could call an event in a way like this without to be worried wherever thread belongs from the main thread:

    MyViewModel : BaseViewModel {

    ..
            TriggerSafeEvent(MyEventHandler, MyEventArgs);

    }

Since the common library is not a WPF application, the App object is not resolved.

I think that this approach could be wrong, however I feel that is not an uncommon practice to share often call methods within a base view model.

What is the best solution to handle with App object?

Upvotes: 1

Views: 365

Answers (1)

Use dependency injection. This is off the top of my head but it'll work.

public interface IDispatcherProvider {
    Dispatcher Dispatcher { get; }
}

BaseViewModel

public static IDispatcherProvider DispatcherProvider { get; set; }

Interface implementation:

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();
        }
    }
    */
}

App

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

Upvotes: 2

Related Questions