我有一个带有TextBox的WPF视图,将Text字段绑定到一个ViewSodel,并将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个字符上我将setter中的文本更改为“ERROR”,并且fire属性发生了更改,则TextBox会更新以显示更改的文本。
那么为什么如果我将setter中的文本改回前一个值,那么UI不能反映这一点?
我知道有其他方法可以处理最大字符,但为什么这不起作用?
答案 0 :(得分:23)
这只不过是框架中的一个错误。 Text
中的TextBox
属性确实获得了新值,但GUI现在与其自己的TextProperty
不同步。如果您想从ViewModel取消ItemsControl
的更改,这也适用于任何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>