设置属性时,PropertyChangedEventHandler为null

时间:2009-11-03 23:18:58

标签: c# wpf inotifypropertychanged

<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:myapp="clr-namespace:MyPlayer.Model"
    mc:Ignorable="d"
    x:Class="MyPlayer.VolumeButtons"
    x:Name="UserControl"
    d:DesignWidth="640" d:DesignHeight="480">
    <UserControl.Resources>
        <myapp:MusicPlayerModel x:Key="Model"/>
    </UserControl.Resources>

    <Grid x:Name="LayoutRoot" DataContext="{StaticResource Model}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="35px"/>
            <ColumnDefinition Width="1.0*"/>
        </Grid.ColumnDefinitions>
        <Slider Value="{Binding Volume}" Margin="0,0,0,0" Grid.Column="1" VerticalAlignment="Center" x:Name="volumeSlider"/>
        <Button Margin="4,4,4,4" Content="Button" x:Name="muteButton" Click="MuteButton_Click"/>
    </Grid>
</UserControl>

现在问题是,当我移动滑块时数据绑定工作正常(当我移动滑块时模型会更新)。

但是,当单击一个按钮时,我会更改模型中的值并希望它更新视图。

以下代码:

private void MuteButton_Click(object sender, RoutedEventArgs e)
{
     musicPlayerModel.Volume = 0;
}

模型中的代码:

public double Volume
{
    get { return this.volume; }
    set 
    { 
         this.volume = value;
         this.OnPropertyChanged("SomeTestText");
         this.OnPropertyChanged("Volume");
    }
}

但是在OnPropertyChanged中,事件为空,因此没有任何反应。为什么事件为空,而不是我的滑块移动时以及如何解决它?

1 个答案:

答案 0 :(得分:2)

您不应直接致电该活动。你正在做的是正确的,但只有正确实现OnPropertyChanged方法。在Microsoft推荐并在整个BCL中使用的模式中,OnPropertyChanged(和任何OnXXXXEventName)应如下所示:

protected override void OnPropertyChanged(PropertyChangedEventArgs e)
{
    // get handler (usually a local event variable or just the event)
    if (this.PropertyChanged != null)
    {
        this.PropertyChanged(this, e);
    }
}

如果这是正确的,您不必担心该事件为空等。但您的代码显示this.OnPropertyChanged("SomeTestText");这是不合法的。该字符串不是有效参数。根据事件模式,OnPropertyChanged事件应如上所示,这意味着您应该按如下方式调用它:

this.OnPropertyChanged(new PropertyChangedEventArgs("Volume"));

注意:如果处理程序(事件)为null,则调用应用程序尚未注册到该事件。通过代码,可以使用somevar.PropertyChanged += handlerMethod完成此操作。


编辑:关于Slider / WPF和事件

在评论中,您建议“应该”自动进行。但是在上面的代码中,您使用字符串调用OnPropertyChanged。如前所述,这不是合法代码,因为OnXXX方法应该有一个继承自EventArgs的参数。虽然我在你的案例中认为是一个正常的PropertyChanged事件,但是XAML和WPF为另一种解释提供了空间(对不起,现在只能达到这个目的)。

你(和我)对一件事情都错了。这个quote from MSDN解释了:

  

“请注意,有一个相同的   用a命名的OnPropertyChanged方法   不同的签名(参数   type是PropertyChangedEventArgs)   可以出现在很多课程上。   OnPropertyChanged用于   数据对象通知,是其中的一部分   的合同   INotifyPropertyChanged的“。

在覆盖Volume属性的代码中需要执行的操作,应该改为调用PropertyChangedCallback,或者使用带有DependencyPropertyChangedEventArgs结构参数的OnXXX代码。如果您问我,即使您不使用原始的WPF方法,您当前的方法也会更容易; - )