使用WPF双向数据绑定时更改setter属性中的值

5

我有一个文本框,它绑定到实体对象上的文本属性。 在某些情况下,我想重新格式化用户输入的文本-例如,如果用户输入“2/4”(一种分数),我想将其更改为“1/2”。

通过Text属性的“set部分”,我可以更改实体对象上的值,但是文本框仍然显示“2/4”,并没有更新为新的值。

2个回答

15
这是因为WPF中的绑定系统非常"智能",当你更改TextBox中的值时,它会假定PropertyChanged事件将对该属性进行触发并忽略它。
您可以通过调用以下方式来强制刷新TextBox的绑定:
textBox.GetBindingExpression(TextBox.TextProperty).UpdateTarget();

但是难点在于找到一个好的地方来挂钩。显然,您的数据对象无法做到这一点,因为它没有对TextBox实例的引用。您可以在持有TextBox的窗口中通过将其链接到数据对象的PropertyChanged事件处理程序来完成,但这并不感觉很干净。
如果我想到更好的解决方案,我会编辑此响应,但至少这解释了绑定不起作用的原因。

啊哈!将绑定更改为IsAsync=true:

<TextBox x:Name="textBox" Text="{Binding Path=TestData, IsAsync=true}"/>

似乎会改变行为,使其在setter触发PropertyChanged事件时注意它。


作为补充(32个月后),这种行为已经在.NET 4中发生了更改,您将不再需要IsAsync。

1
添加 IsAsync=true 对我来说起作用了,但由于现在我的属性被非 GUI 线程使用,导致出现了一些跨线程异常。如果您添加了 IsAsync=true,请确保考虑到线程问题。或者,可以使用这个解决方案代替:http://www.lhotka.net/weblog/DataBindingIssueInWPFWithSolution.aspx。 - Joe Daley
@Joe,感谢您提供的链接!仅添加“IsAsync = true”对我来说并没有起作用,但是添加“Converter = {StaticResource IdentityConverter}”(以及转换器本身)就行了! - mousio
@Martin,感谢您的更新!我没有意识到我的应用程序仍在使用.NET Framework 3.5。切换到.NET Framework 4确实解决了我的问题,所以不需要添加IsAsync=…Converter=… :] - mousio

0

你是否实现了INotifyPropertyChanged并调用了它?

    private string _fraction;

    public string Fraction
    {
        get { return _fraction; }
        set
        {
            _fraction = ReduceFraction(value);
            NotifyPropertyChanged("Fraction");
        }
    }

    private string ReduceFraction(string value)
    {
        string result = "1/2";
        // Insert reduce fraction logic here
        return result;
    }


    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }

是的,您好。但在 .NET 3.5 中更改文本框输入时不会发生任何事情。 - Ievgen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接