As an exercise I decided to create a bicycle gear calculator in WPF. I created two private fields with setters that trigger OnPropertyChanged(), but I have one databound property, ratio, which behaves as “readonly”, because it is dynamically calculated. When I run the program, the textboxes show, the initial values are correctly displayed, the “working” word in the property changed handler is displayed, but the ratio TextBlock doesn’t update.
I suspect this is due to the way the property is “getted”, I wonder if it would be absolutely necessary to add a private field for every, I wonder if there should be any DependencyProperty in this… But actually I have reached my knowledge limit on this and cannot get this trivial program to work.
This is my model:
class SingleGearsetModel : INotifyPropertyChanged
{
public SingleGearsetModel()
{
crank = 44;
cog = 16;
}
private int _crank;
private int _cog;
public int crank {
get{return _crank;}
set{
_crank = value;
OnPropertyChanged("crank");
}
}
public int cog {
get{return _cog;}
set{
_cog = value;
OnPropertyChanged("cog");
}
}
public double ratio
{
get {
return (double)crank / (double)cog;
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string arg)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(arg));
Console.Writeline("working");
}
}
} // end class
This is my XAML:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="CalculadorFixaWPF.MainWindow"
x:Name="Window"
Title="MainWindow"
Width="640" Height="480">
<DockPanel x:Name="LayoutRoot">
<TextBox Text="{Binding crank, Mode=TwoWay}"/>
<TextBox Text="{Binding cog, Mode=TwoWay}"/>
<TextBlock Text="{Binding ratio, StringFormat={}{0:0.00}}"/>
</DockPanel>
</Window>
And this is in my code-behind (MainWindow.xaml.cs):
public partial class MainWindow : Window
{
public MainWindow()
{
this.InitializeComponent();
this.DataContext = new SingleGearsetModel();
}
}
Thanks for reading!
Since Ratio is a calculated field, you want to add a notification every time the value might change. This will happen if
crankorcogare changed.So, after you notify on them being changed, also notify that
ratiohas changed:Same goes for
cog.Edit:
Based on your comments, here is how you can register to the PropertyChanged event from inside your class and raise a PropertyChanged for ratio:
Using this approach, you don’t need to add the
OnPropertyChanged("ratio")inside the setters of the properties – whenever they are raised, you get the event(inSingleGearsetModel_PropertyChanged) and raise theOnPropertyChanged("ratio")