我检查了大约60个国家的邮政编码。用户输入邮政编码,根据该国家/地区的规则进行检查。美国是一个例外,我可以根据已经输入的其他街道地址信息自动填充该值。在某些方面,它基本上是一种自动校正功能。问题是,如果自动填充值与之前的.Text值匹配,则永远不会重新显示 - 用户刚输入的“错误”邮政编码仍会显示!
例如,字段包含“12345”,用户删除“5”,我的属性设置器将值返回“12345”,绑定getter返回“12345”(此时我的_TextChanged事件触发)但是WPF仍显示用户编辑的文本“1234”!
如何强制WPF重新显示该值?
为了简化示例,我对ZipCode值进行了硬编码(在应用程序中,它是以单独的方法计算的):
public String ZipCode
{
get { return _address.ZipCode; }
set
{
_address.ZipCode = "12345";
RaisePropertyChanged("ZipCode");
}
}
这是XAML:
<TextBox Name="ZipBox"
Text="{Binding Path=ZipCode, UpdateSourceTrigger=PropertyChanged}"
TextChanged="ZipBox_TextChanged" />
WPF知道字段已更改,因为它始终触发此事件。但这些方法都没有强制WPF正确显示“12345”。
private void ZipBox_TextChanged(object sender, TextChangedEventArgs e)
{
ZipBox.InvalidateVisual();
ZipBox.InvalidateMeasure();
ZipBox.UpdateLayout();
}
编辑:我还创建了一个自定义静态扩展方法.Refresh(这个UIElement uiElement)调用UIElement.Dispatcher.Invoke()并且也不强制重绘。
答案 0 :(得分:1)
微软论坛上的朱敏想出了一个解决方案。这是代码:
bool flagTextChanged = true;
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
TextBox txt = sender as TextBox;
if (flagTextChanged && txt != null)
{
flagTextChanged = false;
Binding b = BindingOperations.GetBinding(txt, TextBox.TextProperty);
if (b != null)
{
txt.ClearValue(TextBox.TextProperty);
BindingOperations.SetBinding(txt, TextBox.TextProperty, b);
}
flagTextChanged = true;
}
}
答案 1 :(得分:0)
你的意思是在用户手动编辑文本然后离开框后会发生这种情况吗?如果是这样,问题可能是绑定系统不想覆盖用户键入的内容,并且隐含的假设是,如果在属性上调用get,则文本框Text设置的值将与值匹配,因为在集合期间没有抛出异常。这是“魔术属性”的缺点之一,其中设置值被变异而不是经过验证,因为有许多属性的消费者假设如果setter没有抛出异常,则以下内容为真:
Instance.X = value;
Debug.Assert(Instance.X == value);
避免此问题的一个想法是设置一个标志,禁止编辑ZipCode字段(如果已自动确定)(通过绑定IsReadOnly,可能。)
答案 2 :(得分:0)
我相信如果你把一个自定义的IValueConverter除了返回传递的值之外什么都不做,那么TextBox会正确更新。
否则,您应该可以:
ZipBox.GetBindingExpression(TextBox.TextProperty).UpdateTarget();
答案 3 :(得分:0)
这是一个老问题,但它从来没有得到妥善回答,所以这是我的建议。
您需要实施INotifyPropertyChanged
。
取决于它是ViewModel还是Window的代码隐藏(这是一个Window示例):
public class MyWindow: Window, INotifyPropertyChanged
{
...
}
然后在该类中实现一个版本的INotifyPropertyChanged(那里有很多,但这是我使用的版本):
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
private bool SetField<T>(ref T field, T value, string propertyName)
{
if (EqualityComparer<T>.Default.Equals(field, value))
{
return false;
}
field = value;
OnPropertyChanged(propertyName);
return true;
}
然后只需将它与属性一起使用:
private string _text;
public string Text
{
get { return _text; }
set { SetField(ref _text, value, "Text"); }
}
答案 4 :(得分:-3)
我对WPF并不是特别熟悉,但我做了很多网页编程。您可以尝试触发帖子来重新加载整个页面(或只是带有ajax的文本框),这应该允许您设置新值。