我的usercontrol如何通知我的视图?

时间:2014-06-12 17:50:25

标签: c# wpf model-view-controller mvvm user-controls

在WPF中我试图尽可能地成为MVC / VM。我有一个用户控件(ReservationDataControl),它有一个带有上下文菜单和一些过滤器按钮的数据网格。用户可以从上下文菜单中添加,删除等,它们都在usercontrol中处理。此控件与另一个用户控件位于同一窗口,我收集有关已付人数和获得的数量的统计信息(PartyStatsControl)。

当用户编辑ReservationDataControl时,我需要PartyStatsControl进行更新(因此它们将有效)。什么是最好的MVC / VM方式?

我应该从ReservationDataControl举起一个事件吗?有没有办法绑定命令?控件在MVC / VM中通知其主机更改的可接受方式是什么。

顺便说一句:我使用MVC / VM是因为我从来没有设法在我的头脑中得到两者之间的差异,而不是与我正在使用的方法论争论我只是警察不知道马上蝙蝠

1 个答案:

答案 0 :(得分:0)

与大多数工程设计一样,没有正确错误答案,这一切都取决于方案。在后面的代码中处理事件并适当地调用视图模型是完全正确的(假设您在实例化时已将视图模型的引用传递到视图中)。

然而,您可以绑定命令,我更喜欢这种方法,因为它更松散耦合。此命令中的操作将设置模型(在这种情况下,在创建 ReservationDataViewModel 时传入的 _statistics 实例)。

ReservationDataControl查看:

<Button Command={Binding ClickCommand}/>

ReservationDataControl视图模型(数据上下文):

private readonly Statistics _statistics;

public ICommand ClickCommand { get; set; }

private ReservationDataViewModel(Statistics statistics)
{
    _statistics = statistics;

    InitialiseCommands();
}

private void InitialiseCommands()
{
    ClickCommand = new RoutedUICommand("ClickCommand", "ClickCommand", typeof(ViewModel));
    CommandBinding clickCommandBinding = new CommandBinding(ClickCommand, ExecuteClickCommand, ClickCommandCanExecute);
    CommandManager.RegisterClassCommandBinding(typeof(ViewModel), clickCommandBinding);
}

private void ExecuteClickCommand(object sender, ExecutedRoutedEventArgs args)
{
    // perform click logic here...

    // e.g. say there is a property on your statistics called 'ReservationCount'
    // the command adds a reservation (increments the count)
    _statistics.ReservationCount += 1;
}

private void ClickCommandCanExecute(object sender, CanExecuteRoutedEventArgs args)
{
    args.CanExecute = true; // put your can execute logic here...
}

现在,如果您的模型(即统计类)设置正确,它应该能够告诉任何关心它已经更改的代码。

public class Statistics
{
    public event EventHandler ReservationCountChanged;

    private int _reservationCount;

    // think about how you may restrict set access for this model
    public int ReservationCount 
    { 
        get { return _reservationCount; } 
        protected set
        {
            if (_reservationCount != value)
            {
                _reservationCount = value;

                if (ReservationCountChanged != null)
                    ReservationCountChanged(this, new EventArgs());
            }
        }
    }

    public Statistics() { }
}

现在, PartyStatsViewModel 可以从 ReservationDataViewModel 中获取此更改,并使用标准WPF绑定实现更新其视图。

PartyStatsControl查看模型:

private readonly Statistics _statistics;

public int ReservationCount
{
    get { return _statistics.ReservationCount; }
    set
    {
        _statistics.ReservationCount = value;

        OnPropertyChanged("ReservationCount");
    }
}               

public PartyStatsControlViewModel(Statistics statistics)
{
    _statistics = statistics;

    _statistics.ReservationCountChanged += OnReservationCountChanged;
}

private void OnReservationCountChanged(object sender, RoutedEventArgs args)
{
    // todo: force this onto the UI thread or exceptions will occur
    this.ReservationCount = ((Statistics)sender).ReservationCount;
}