使用OnPropertyChanged事件要求应用程序执行某些操作是否正确?

时间:2012-02-22 16:19:06

标签: wpf mvvm

我的MVVM应用程序包含两个视图:

  • AllStrategiesView
  • StrategyView

当用户在AllStrategiesView StrategyView中单击某个策略时,会创建此策略。我使用这样的代码来通知应用程序应该创建StrategyView:

    .............
    public void OpenStrategyView()
    {
        OnPropertyChanged("OpenStrategy");
    }
    .................
    private void OnWorkspacePropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        const string openStrategyString = "OpenStrategy";
        if (e.PropertyName == openStrategyString)
        {
            AllStrategiesViewModel vm = (sender as AllStrategiesViewModel);
            OpenStrategy(vm.SelectedStrategy);
        }
    }

然而程序的另一部分显示错误消息,因为没有这样的属性“OpenStrategy”:

    /// <summary>
    /// Warns the developer if this object does not have
    /// a public property with the specified name. This 
    /// method does not exist in a Release build.
    /// </summary>
    [Conditional("DEBUG")]
    [DebuggerStepThrough]
    public void VerifyPropertyName(string propertyName)
    {
        // Verify that the property name matches a real,  
        // public, instance property on this object.
        if (TypeDescriptor.GetProperties(this)[propertyName] == null)
        {
            string msg = "Invalid property name: " + propertyName;

            if (this.ThrowOnInvalidPropertyName)
                throw new Exception(msg);
            else
                Debug.Fail(msg);
        }

问题是:

使用OnPropertyChanged通知应用程序需要执行某些操作是对还是错?我应该重写我的代码以免使用OnPropertyChanged还是禁用VerifyPropertyName代码?

3 个答案:

答案 0 :(得分:0)

这是不好的做法。 PropertyChanged上的INotifyPropertyChanged事件应该用于通知订阅者对象实例上的属性已更改。这通常在WPF中用于通知UI它需要使用新的属性值更新自己。

在MVVM中,您应该使用某种命令或替代视图模型/视图通信机制来从视图中调用视图模型上的动词(方法)。 WPF提供的命令有局限性,因此我建议使用MVVM framework及其提供的机制。

答案 1 :(得分:0)

这取决于你想要它做什么。在您的情况下,您看起来有一个属性“Workspace”,它指示您应该查看哪个VM。对于恕我直言,这似乎并不太糟糕。

如果你做了一些与被改变的属性完全无关的东西,那么它可能会起作用,但它肯定不是我期望它做的(见Principle of Least Astonishment)。 OnPropertyChanged旨在表明已绑定的属性已更改并应重新获取。

您当然可以在ViewModel上再举办一次活动,例如:

public event Action<String> OpenStrategy;

还有一件事......这段代码完全是多余的:

const string openStrategyString = "OpenStrategy";
if (e.PropertyName == openStrategyString)

从编译器的角度来看,以下内容完全相同,而且更具可读性:

if (e.PropertyName == "OpenStrategy")

答案 2 :(得分:0)

要求您的应用程序在PropertyChanged事件中执行某些操作并没有错,但是不要仅仅为了请求应用程序执行某事而引发PropertyChanged事件。

PropertyChanged用于表示属性已更改,应仅用于此属性。

Devdigital's answer提供了一个很好的示例,即UI使用PropertyChange通知来了解它应该何时更新。其他对象也可以订阅接收更改通知,并且只应在值更改时通知它们,而不是在您想要运行某些应用程序代码时通知。

使用你的例子,我会像这样重写它:

public void OpenStrategyView()
{
    OpenStrategy(this.SelectedStrategy);
}

private void OnWorkspacePropertyChanged(object sender, PropertyChangedEventArgs e)
{
    if (e.PropertyName == "SelectedStrategy")
    {
        OpenStrategyView();
    }
}