I'm trying to bind the <Visibility>
attribute of a button to a boolean property of a custom class, but I'm failing to get any notifications back.
I have the following property in my viewmodel:
public MediaPlayerModel MediaPlayer { get; set; }
Where the type is written as follows:
public class MediaPlayerModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private MediaPlayerState _currentState;
public MediaPlayerState CurrentState
{
get => _currentState;
protected set
{
if (!Equals(value, _currentState))
{
_currentState = value;
OnPropertyChanged();
}
}
}
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}
}
And MediaPlayerState
is declared as follows:
[Serializable]
public sealed class MediaPlayerState : BaseState
{
public bool IsRunning { get; }
//..
}
public class BaseState : IEquatable<BaseState> {..}
I then have the following xaml code:
<Button Content="Button" HorizontalAlignment="Left" Margin="212,337,0,0" VerticalAlignment="Top" Width="74"
Visibility="{Binding MediaPlayer.CurrentState, Converter={converters:TestConverter}}">
</Button>
Where converters:TestConverter
is implemented as follows:
[ValueConversion(typeof(MediaPlayerState), typeof(Visibility))]
public class TestConverter : BaseConverter, IValueConverter
{
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
var running = ((MediaPlayerState)value).IsRunning;
if (running)
{
return Visibility.Visible;
}
return Visibility.Hidden;
}
public object ConvertBack(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
return null;
}
}
The visibility of the button never changes and the converter's method are never invoked.
I did come up with an alternative solution but it seems like a hack to me and not a proper fix and it opens a door for other potential bugs.
I'm binding the visibility attribute to the MediaPlayer
property itself not the nested one:
Visibility="{Binding MediaPlayer... unchanged}
Than I'm subscribing to the PropertyChanged
event from the MediaPlayerModel
class during the Loaded
event of the main window:
MediaPlayer.PropertyChanged += MediaPlayerOnPropertyChanged;
Where the event handler is implemented as follows:
private void MediaPlayerOnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(MediaPlayer.CurrentState))
{
OnPropertyChanged(nameof(MediaPlayer));
}
}
This makes it work, but it's pretty weird as this proofs that the event is actually fired at the right times, but the binding doesn't seems to work.
What is the cause of that? Why am I unable to bind to a nested property which has a working INotifyPropertyChanged
event firing? And what's the fix to it?