如何阻止WPF绑定忽略其引起的PropertyChanged事件?

3
我有一个绑定到ViewModel的Text属性的TextBox,具有以下设置:
Xaml
<TextBox Text="{Binding Text}"/>

C#
public class ViewModel : INotifyPropertyChanged
{
    public string Text
    {
        get
        {
            return m_Text;
        }
        set
        {
            if (String.Equals(m_Text, value))
            {
                return;
            }

            m_Text = value.ToLower();
            RaisePropertyChanged("Text");
        }
    }

    // Snip
}

当我在文本框中输入一些内容时,它成功地设置了ViewModel的Text属性。问题是,WPF忽略了由其自己的更新引发的属性更改事件。这导致用户看不到他们键入的文本转换为小写字母。
我该如何改变这种行为,使得文本框更新为小写字母的文本?
注意:这只是我用来说明WPF忽略事件问题的示例。我并不真正关心将字符串转换为小写字母或任何涉及String.Equals(string, string)的问题。
4个回答

2
您可以通过使用Dispatcher.BeginInvoke在单独的调度程序调用中引发事件来实现此目的。
定义一个委托:
private delegate void RaisePropertyChangedDelegate(string property);

然后使用以下代码来触发该事件。
Dispatcher.CurrentDispatcher.BeginInvoke(
    DispatcherPriority.Normal,
    new RaisePropertyChangedDelegate(RaisePropertyChanged), 
    "Text");

我并不是很喜欢这个解决方案,因为它要求绑定对象知道调度程序的存在。然而,它确实解决了问题,所以我把它标记为答案。 - Jacob Stanley

2

显然,这个问题在2010年发布的.NET Framework 4.0中的WPF 4.0中得到了解决:Karl Shifflett的博客


0
你需要强制更新绑定目标(请参见MSDN上的这篇文章)。但是,在WPF4中已经更改/损坏了此功能,因此您必须改为对源进行强制更新(请参见this post)。

0

我记得 Rocky Lhotka 在一期旧的 .NET Rocks 节目中抱怨过这种行为。 (搜索了半个小时...)啊,我们找到了。2006年3月第169集

所以,如果你在Windows表单中有一个详细的表单,那么你可以将所有属性绑定到不同的文本框中,当用户输入内容并切换焦点时,该值会被放入对象中,但你的对象可能会更改该值,例如可能存在某种操作,要求所有字母都必须是大写字母,这是一项业务规则,因此需要在对象中设置。如果这样做,UI界面中就无法显示出更改后的值。换句话说,用户可以输入小写字母a、b、c,然后切换焦点。这些小写字母仍将保留在文本框中。稍后,当他们更改其他字段时,他们将记住将对象值转换为大写字母。因此,对象具有大写字母a、b、c,而UI错误地显示为小写字母。然后用户更改其他控件并切换焦点,突然间,之前未更改的大写字母a、b、c出现在了他们没有停留过的文本框中。

Rocky并没有真正提出问题的解决方案,我敢说如果他还没有想到一个好的答案,也许就是没有。也许你需要从代码后台订阅对象的PropertyChanged事件,并在相关属性改变时手动刷新绑定。

附注:这并不是直接回答你的问题,但是在你给出的示例中,你可以设置TextBox上的CharacterCasing,使其仅接受小写字符。


哈哈,我开始回答这个问题,然后出去喝茶了。5个小时后我回来看到你更新了你的问题,预防我谈论字符大小写。噢好吧,;-) - Matt Hamilton

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