WPF - MVVM - 文本框与 viewmodel 属性不同步 [英] WPF - MVVM - Textbox getting out of sync with viewmodel property

查看:15
本文介绍了WPF - MVVM - 文本框与 viewmodel 属性不同步的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有 TextBox 的 WPF 视图,将 Text 字段绑定到一个 ViewModel,UpdateSourceTrigger 设置为 PropertyChanged.在 ViewModel 的属性设置器中,我有一个简单的检查,以防止文本超过 10 个字符:

I have a WPF view with a TextBox, binding the Text field to a ViewModel with UpdateSourceTrigger set to PropertyChanged. In the property setter in the ViewModel, I have a simple check to prevent the text from exceeding 10 characters:

<TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        this.DataContext = new MainViewModel();
    }
}


public string Name
{
    get { return _Name; }
    set
    {
        if (_Name != value)
        {
            if (value.Length <= 10)
            {
                _Name = value;
            }
            RaisePropertyChanged("Name");
        }
    }
}

如果未设置该值,我仍然使用 RaisePropertyChanged(它只是触发 PropertyChanged).

If the value isn't set, I still RaisePropertyChanged (which simply fires PropertyChanged).

问题是当我在 UI 中输入第 11 个字符时,我没有更新 _Name.我触发了 PropertyChanged,我可以看到 get 访问器被调用,它返回只有 10 个字符的字符串.但是,我的 TextBox 没有反映这一点;它仍然显示具有 11 个字符的字符串.

The problem is that when I type in the 11th character in the UI, I don't update _Name. I fire PropertyChanged, and I can see the get accessor get called and it returns the string with only 10 characters. However, my TextBox doesn't reflect this; it still shows the string with 11 characters.

最重要的是,如果在第 11 个字符上我将 setter 中的文本更改为ERROR",并且 fire 属性发生更改,则 TextBox 会更新以显示更改后的文本.

On top of that, is that if on the 11th character I change the text in the setter to "ERROR", and fire property changed, the TextBox DOES update to show the altered text.

那么为什么如果我将 setter 中的文本改回以前的值,UI 不会反映这一点?

So why is it that if I alter the text in the setter back to the previous value, the UI doesn't reflect this?

我知道有其他方法可以处理最大字符数,但为什么这行不通?

I know there are alternative ways of handling max characters, but why won't this work?

推荐答案

这只不过是框架中的一个错误.TextBox 中的 Text 属性确实获得了您的新值,但 GUI 现在与其自己的 TextProperty 不同步.当您想从 ViewModel 中取消 SelectedItem 的更改时,任何 ItemsControl 也会发生这种情况,这真的很烦人.

This is nothing but a bug in the framework. The Text property in the TextBox does get your new value but the GUI is now out of sync with its own TextProperty. This also happends for any ItemsControl when you want to cancel a change of SelectedItem from the ViewModel and it's really annoying.

当您使用显式 Binding 时不会发生此错误,因此可以将其用作解决方法.

This bug doesn't happend when you use explicit Binding though so this can be used as a workaround.

Xaml

<TextBox Text="{Binding Path=MyName,
                        UpdateSourceTrigger=Explicit}"
         TextChanged="TextBox_TextChanged"/>

背后的代码

private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
    TextBox textBox = sender as TextBox;
    textBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();
}

要验证 TextBox GUI 确实不同步,只需观察 TextBox.Text 的值.例如,TextBox 会说123456789___0",而 TextBlock 会说123456789".

To verify that the TextBox GUI indeed is out of sync, just observe the value of TextBox.Text. The TextBox will say "123456789___0" for example while TextBlock says "123456789".

<StackPanel>
    <TextBox Name="myTextBox"
             Text="{Binding Path=MyName,
                            UpdateSourceTrigger=PropertyChanged}"/>
    <TextBlock Text="{Binding ElementName=myTextBox, Path=Text}"/>
</StackPanel>

这篇关于WPF - MVVM - 文本框与 viewmodel 属性不同步的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆