MVVM - DataContext&众多ViewModels

时间:2015-03-09 12:19:20

标签: c# wpf mvvm

我一直在尝试将MVVM设计模式应用到我的最新项目中。我观看了无数的视频,阅读了大量的教程,同时也查看了人们的演示代码。

我有一个Job对象和一个Task对象。我为每个人创建了一个ViewModel。我还创建了一个AllJobs和AllTask​​s ViewModel,分别创建ObservableCollection JobViewModelsTaskViewModels

如果我将MainWindow的DataContext设置为AllJobsViewModel的实例,那么我可以访问ObservableCollection名为' AllJobs'并按我的意愿使用它。但是,假设这是DataContext,那么如何在同一窗口中访问我的AllTask​​sViewModel AllTask​​s集合呢?

4 个答案:

答案 0 :(得分:1)

如果您将ViewModel设计为镜像业务对象,那么您的方向是错误的。相反,ViewModel应该特定于视图。 ViewModel与其视图之间应该存在严格的1:1关系 - 换句话说:它们形成

模型部分独立于此区别,这完全取决于业务案例和您要定位的平台。

您的要求(用例)管理您的应用程序的视图部分。业务域管理模型的设计。然后,ViewModel将在两者之间进行调解。它仅满足应用程序视图部分的技术要求。

答案 1 :(得分:0)

对于模型和视图模型,很少有1:1的关系。您可以将ViewModel组合成多个模型甚至多个视图模型。我相信这也是您情况下的首选解决方案。

MVVM背后的主要观点是尽可能地分离图层,尤其是UI和模型。请参阅我的最新答案,了解What goes into the Model/Viewmodel?

的含义

答案 2 :(得分:0)

您无需为每个项目创建单独的视图模型。您需要创建一个包含所需信息的单一视图模型,并将该视图模型作为主窗口的DataContext。

或者,创建另一个包含AllJobsViewModel和AllTask​​sViewModel的viewmodel。并将新的viewmodel作为MainWindow的datacontext。

答案 3 :(得分:0)

您可以使用EventAggregatorMessageBus

我们的想法是让您的视图模型订阅他们想要响应的事件。

我使用 发布订阅模式 来处理复杂的类依赖项:

<强>视图模型:

    public class ViewModel : ViewModelBase
    {
        public ViewModel()
        {
            CloseComand = new DelegateCommand((obj) =>
                {
                    MessageBus.Instance.Publish(Messages.REQUEST_DEPLOYMENT_SETTINGS_CLOSED, null);
                });
        }
}

<强>窗口:

public partial class SomeWindow : Window
{
    Subscription _subscription = new Subscription();

    public SomeWindow()
    {
        InitializeComponent();

        _subscription.Subscribe(Messages.REQUEST_DEPLOYMENT_SETTINGS_CLOSED, obj =>
            {
                this.Close();
            });
    }
}

您可以利用Bizmonger.Patterns获取MessageBus。

<强> MessageBus

public class MessageBus
{
    #region Singleton
    static MessageBus _messageBus = null;
    private MessageBus() { }

    public static MessageBus Instance
    {
        get
        {
            if (_messageBus == null)
            {
                _messageBus = new MessageBus();
            }

            return _messageBus;
        }
    }
    #endregion

    #region Members
    List<Observer> _observers = new List<Observer>();
    List<Observer> _oneTimeObservers = new List<Observer>();
    List<Observer> _waitingSubscribers = new List<Observer>();
    List<Observer> _waitingUnsubscribers = new List<Observer>();

    int _publishingCount = 0;
    #endregion

    public void Subscribe(string message, Action<object> response)
    {
        Subscribe(message, response, _observers);
    }

    public void SubscribeFirstPublication(string message, Action<object> response)
    {
        Subscribe(message, response, _oneTimeObservers);
    }

    public int Unsubscribe(string message, Action<object> response)
    {
        var observers = new List<Observer>(_observers.Where(o => o.Respond == response).ToList());
        observers.AddRange(_waitingSubscribers.Where(o => o.Respond == response));
        observers.AddRange(_oneTimeObservers.Where(o => o.Respond == response));

        if (_publishingCount == 0)
        {
            observers.ForEach(o => _observers.Remove(o));
        }

        else
        {
            _waitingUnsubscribers.AddRange(observers);
        }

        return observers.Count;
    }

    public int Unsubscribe(string subscription)
    {
        var observers = new List<Observer>(_observers.Where(o => o.Subscription == subscription).ToList());
        observers.AddRange(_waitingSubscribers.Where(o => o.Subscription == subscription));
        observers.AddRange(_oneTimeObservers.Where(o => o.Subscription == subscription));

        if (_publishingCount == 0)
        {
            observers.ForEach(o => _observers.Remove(o));
        }

        else
        {
            _waitingUnsubscribers.AddRange(observers);
        }

        return observers.Count;
    }

    public void Publish(string message, object payload)
    {
        _publishingCount++;

        Publish(_observers, message, payload);
        Publish(_oneTimeObservers, message, payload);
        Publish(_waitingSubscribers, message, payload);

        _oneTimeObservers.RemoveAll(o => o.Subscription == message);
        _waitingUnsubscribers.Clear();

        _publishingCount--;
    }

    private void Publish(List<Observer> observers, string message, object payload)
    {
        Debug.Assert(_publishingCount >= 0);

        var subscribers = observers.Where(o => o.Subscription.ToLower() == message.ToLower());

        foreach (var subscriber in subscribers)
        {
            subscriber.Respond(payload);
        }
    }

    public IEnumerable<Observer> GetObservers(string subscription)
    {
        var observers = new List<Observer>(_observers.Where(o => o.Subscription == subscription));
        return observers;
    }

    public void Clear()
    {
        _observers.Clear();
        _oneTimeObservers.Clear();
    }

    #region Helpers
    private void Subscribe(string message, Action<object> response, List<Observer> observers)
    {
        Debug.Assert(_publishingCount >= 0);

        var observer = new Observer() { Subscription = message, Respond = response };

        if (_publishingCount == 0)
        {
            observers.Add(observer);
        }
        else
        {
            _waitingSubscribers.Add(observer);
        }
    }
    #endregion
}

}

<强>订阅

public class Subscription
{
    #region Members
    List<Observer> _observerList = new List<Observer>();
    #endregion

    public void Unsubscribe(string subscription)
    {
        var observers = _observerList.Where(o => o.Subscription == subscription);

        foreach (var observer in observers)
        {
            MessageBus.Instance.Unsubscribe(observer.Subscription, observer.Respond);
        }

        _observerList.Where(o => o.Subscription == subscription).ToList().ForEach(o => _observerList.Remove(o));
    }

    public void Subscribe(string subscription, Action<object> response)
    {
        MessageBus.Instance.Subscribe(subscription, response);
        _observerList.Add(new Observer() { Subscription = subscription, Respond = response });
    }

    public void SubscribeFirstPublication(string subscription, Action<object> response)
    {
        MessageBus.Instance.SubscribeFirstPublication(subscription, response);
    }
}
相关问题