10

作为练习,我决定在 WPF 中创建一个自行车齿轮计算器。我使用触发的设置器创建了两个私有字段OnPropertyChanged(),但我有一个数据绑定属性,ratio它表现为“只读”,因为它是动态计算的。当我运行程序时,显示文本框,正确显示初始值,显示属性更改处理程序中的“工作”字,但ratioTextBlock 不更新。

我怀疑这是由于“获取”属性的方式,我想知道是否绝对有必要为每个添加一个私有字段,我想知道这是否应该有任何 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();
    }
}

谢谢阅读!

4

2 回答 2

13

由于比率是一个计算字段,因此您希望在每次值可能更改时添加通知。如果更改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");
        }
}

使用这种方法,您不需要OnPropertyChanged("ratio")在属性的 setter 内部添加 - 每当它们被引发时,您都会得到 event(in SingleGearsetModel_PropertyChanged) 并引发OnPropertyChanged("ratio")

于 2013-01-29T19:09:26.333 回答
2

最简单的方法就是将 和 都添加OnPropertyChanged("ratio")到设置器crankcog。你可以做一些更复杂的事情,比如监听OnPropertyChanged事件crank并在它们中的任何一个发生变化时cog自动触发OnPropertyChanged("ratio"),但这至少会让你继续前进。

于 2013-01-29T19:09:31.993 回答