(before starting : I'm using .NET Framework 4.8)
I've been fooling around in WPF and I was getting tired of constantly typing out properties that are used for bindings. I am now using code snippets to type out boiler plate code.
After a while, I got sick of always pasting the notify property changed code in each 'model', and I created a BindableBase, which I've learned since is kind of common practice. The class which looks like this:
public class BindableBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
/// <summary>
/// Sets the value of a field of type T. <br/>
/// If new field value differs from old value, the funtion returns true. <br/>
/// If the value remains unchanged, the function returns false.
/// </summary>
/// <typeparam name="T">The type of the property / field.</typeparam>
/// <param name="field">A reference to the field that should be updated.</param>
/// <param name="value">The new value to be assigned to the property / field.</param>
/// <param name="propertyName">The variable name in code. Leave empty to let the compiler do this for you.</param>
/// <returns>True on field value change, false if field value remains the same.</returns>
protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
field = value;
OnPropertyChanged(propertyName);
return true;
}
public delegate void PropertyValueChangedEventHandler<T>(T newValue);
}
My properties look like this
private object privateProp;
public object PublicProp
{
get => privateProp;
set => SetField(ref privateProp, value);
}
One thing I dislike about properties that have to call OnPropertyChanged is that they add so much code and in my opinion kind of bloat the source code. Today I tried to create a way to not have to write (generate with snippet) the whole property out everywhere.
public class BindableProperty<T> : BindableBase
{
private T value;
public T Value
{
get => value;
set => SetField(ref value, value);
}
}
Which I wanted to use as follows:
<StackPanel Name="PermissionsPanel">
<CheckBox Name="ReadCheckBox" IsChecked="{Binding ReadFlag.Value}" />
<CheckBox Name="WriteCheckBox" IsChecked="{Binding WriteFlag.Value}" />
<StackPanel />
public class Permissions
{
BindableProperty<bool> ReadFlag = new BindableProperty<bool>();
BindableProperty<bool> WriteFlag = new BindableProperty<bool>();
}
// ...
public class SomeWindow : Window
{
privatye readonly Permissions permissions = new Permissions();
public SomeWindow()
{
InitializeComponent();
PermissionsPanel.DataContext = permissions;
}
}
This looked like a very clean solution to not having the same boilerplate code everywhere. Sadly, it doesn't seem to work.
Can anyone tell the reason why this doesn't work? Or if, with a tweak, this could work?
You may want to consider using a source generator such as Fody. At compile time, it injects code that raises the
PropertyChangedevent.ReadFlagandWriteFlagmust be public properties for you to be able to bind to them: