Question

<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>

Now the thing is, databinding is working correct when I am moving my slider(the model is updated when I am moving the slider).

However when a button is clicked I change the value in the model and expects it to update the view.

Code below:

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

Code in model:

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

But in OnPropertyChanged, the event is null and therefor nothing happens. Why is the event null and not when my slider is moving and how to solve it?

Was it helpful?

Solution

You should not call the event directly. What you are doing is correct, but only if the OnPropertyChanged method is implemented correctly. In the pattern recommended by Microsoft and used throughout the BCL, the OnPropertyChanged (and any OnXXXXEventName) should look as follows:

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

If this is correct, you shouldn't need to worry about the event being null etc. But your code shows this.OnPropertyChanged("SomeTestText"); which is not legal. The string is not a valid parameter. According to the event pattern, the OnPropertyChanged event should look as above, which means you should call it as follows:

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

Note: if the handler (event) is null, then the calling application has not been registered to the event. Through code, this can be done with somevar.PropertyChanged += handlerMethod.


Edit: about Slider / WPF and events

In a comment you suggest that it "should" go automatically. But in the code above, you call OnPropertyChanged with a string. As mentioned before, that's not legal code, because OnXXX methods should have one parameter which inherits from EventArgs. Though I considered a normal PropertyChanged event in your case, XAML and WPF gave room for another interpretation (sorry for only getting to this now).

You (and I) were mistaken about one thing. This quote from MSDN explains that:

"Note that there is an identically named OnPropertyChanged method with a different signature (the parameter type is PropertyChangedEventArgs) that can appear on a number of classes. That OnPropertyChanged is used for data object notifications, and is part of the contract for INotifyPropertyChanged."

What you need to do in the code where you override the Volume property, you should call PropertyChangedCallback instead, or use your OnXXX code with as parameter a DependencyPropertyChangedEventArgs structure. If you ask me, your current approach is way easier, even though you don't use the original WPF methods ;-)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top