10

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

<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)。

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

最重要的是,如果在第 11 个字符上我将设置器中的文本更改为“错误”,并且触发属性发生了更改,则 TextBox 会更新以显示更改后的文本。

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

我知道有处理最大字符的替代方法,但为什么这不起作用?

4

1 回答 1

24

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

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

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”。

<StackPanel>
    <TextBox Name="myTextBox"
             Text="{Binding Path=MyName,
                            UpdateSourceTrigger=PropertyChanged}"/>
    <TextBlock Text="{Binding ElementName=myTextBox, Path=Text}"/>
</StackPanel>
于 2012-05-31T20:40:39.027 回答