通知WPF中计算的数据绑定属性的更改

时间:2013-01-29 19:06:05

标签: wpf data-binding notifications

作为练习,我决定在WPF中创建一个自行车齿轮计算器。我创建了两个私有字段,其中包含触发OnPropertyChanged()的setter,但我有一个数据绑定属性ratio,其行为为" readonly",因为它是动态计算的。当我运行程序时,文本框显示,初始值正确显示,"工作"显示属性更改处理程序中的单词,但ratio TextBlock不会更新。

我怀疑这是由于该属性的方式" getted",我想知道是否绝对有必要为每个人添加一个私有字段,我想知道是否应该有任何DependencyProperty。 ..但实际上我已经达到了我的知识限制,无法让这个简单的程序工作。


这是我的模特:

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

这是我的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>

这是我的代码隐藏(MainWindow.xaml.cs):

public partial class MainWindow : Window
{
    public MainWindow()
    {
        this.InitializeComponent();
        this.DataContext = new SingleGearsetModel();
    }
}

感谢阅读!

2 个答案:

答案 0 :(得分:7)

由于Ratio是计算字段,因此您希望每次值更改时添加通知。如果更改了crankcog,就会发生这种情况。

因此,在您通知他们被更改之后,还要通知ratio已更改:

public int crank 
{ 
    get{return _crank;}
    set{
        _crank = value;
        OnPropertyChanged("crank");

        // *** Notify that ratio has also been changed ***
        OnPropertyChanged("ratio");
    }
}

同样适用于cog

修改 根据您的意见,以下是如何从类中注册PropertyChanged事件并提升PropertyChanged的比率:

// Constructor
public SingleGearsetModel()
{
    ....
   PropertyChanged += SingleGearsetModel_PropertyChanged;
}

// PropertyChanged event handler
void SingleGearsetModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
        if (e.PropertyName == "cog" || e.PropertyName == "crank")
        {
            OnPropertyChanged("ratio");
        }
}

使用这种方法,您不需要在属性的setter中添加OnPropertyChanged("ratio") - 无论何时引发它们,您都会获得事件(在SingleGearsetModel_PropertyChanged中)并提升{{1 }}

答案 1 :(得分:2)

最简单的方法就是将OnPropertyChanged("ratio")添加到crankcog的设置者中。您可以在监听来自OnPropertyChangedcrank的{​​{1}}事件时执行更复杂的操作,并在其中任何一个更改时自动触发cog,但这至少会让你去。