INotifyPropertyChanged的问题
-
20-08-2019 - |
题
目前我想先说低于样品是过于简单化。 假设你已绑定WPF控制。
<Window Title="Window1" Height="300" Width="300">
<Grid>
<StackPanel>
<TextBox Text="{Binding Name}" Margin="10"/>
<Button HorizontalAlignment="Center"
Content="Click Me" Margin="5"
Padding="2" Click="OnButtonClick" />
</StackPanel>
</Grid>
</Window>
窗口被绑定到其实现INotifyPropertyChanged
并且具有名称设定器在形式Person类
public string Name
{
get { return _name; }
set
{
_name = "Some Name";
OnPropertyChanged("Name");
}
}
即。每当用户试图将其从UI改变_name分配“有些名称”。 但这个样品不工作。虽然PropertyChanged事件被触发我在文本框名称更改为某个值按tab迫使焦点移动到文本框按钮和值保持不变。
能否请你解释一下我为什么会发生?据我所知PropertyChanged
事件强制UI从属性重读值,并显示它们,但在数据绑定文本框我的示例值不被更新。
再次。我明白,这是执行不力的财产和,但我想重申,这是过于简单化了。 这仅仅是一个样品。 但无论如何,信号的PropertyChanged该属性被更改,应该更新,但事实并非如此。
解决方案
在PropertyChanged事件是由文本框忽略,因为它是事件的发起者。
一些澄清:
在文本框(或文本框的结合)知道它是引发剂,因为它在接收同一呼叫PropertyChanged事件。通过这样做异步调用,文本框(或结合)没有办法知道它是发起者,所以它会处理该事件,就好像别人已经更新了它
如果你添加一个文本框2号到您的UI,你会看到,当你编辑1,和周围的其他方式的第二个文本框不会改变。
其他提示
通过Heinzi建议虚设转换器的解决方法(描述这里)不起作用当结合的 UpdateSourceTrigger 是的PropertyChanged 。但是,如果这是我们所需要的?
看来使结合 - 异步是卓有成效的,e.g:
SelectedIndex="{Binding SelectedIndex, IsAsync=True}"
正如气泡布已经指出的,这是由设计 - 文本框假定如果它设置一个绑定属性为某个值,该设定器将不会改变该值。 根据微软一>,它们将不改变这种行为,因为这将破坏现有的代码。
如果您的要的更改值(是的,有非常充分的理由这样做),你必须使用一种解决方法,例如,加上空转换器。有博客条目(不是我写的),在详细描述了这种技术。
的原因是因为你在二传手硬编码“有些名称”。当你改变文本框的值设置器实际上得到调用,它重新设置“有些名称”作为这样的PropertyValue似乎犯规在UI改变。
把_name = value
,事情只会工作,如你预期,
public string MyField
{
get { return _myField; }
set {
if (_myField == value)
return;
_myField = value;
OnPropertyChanged("MyField");
}
}
这是正确执行的属性。
当您更改属性,确保对象完全相同的实例绑定到一个控制。否则,这种变化将被通报,但控制将永远不会得到它,因为该控件没有正确绑定。
在形式更换设定器
set
{
_name = "Some Name";
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.DataBind,
(SendOrPostCallback)delegate { OnPropertyChanged("Name"); },
null);
}
解决问题,但它仍然是开放的。为什么要让异步调用,而不是同步信号,我的财产已被更改。
如果我没有记错的话,默认绑定的文本框的Text属性的行为是双向,所以这应该工作。可以强制它是双向这样在XAML:
<Window Title="Window1" Height="300" Width="300">
<Grid>
<StackPanel>
<TextBox Text="{Binding Name, Mode=TwoWay}" Margin="10"/>
<Button HorizontalAlignment="Center"
Content="Click Me" Margin="5"
Padding="2" Click="OnButtonClick" />
</StackPanel>
</Grid>
</Window>
请注意在绑定声明Mode=TwoWay
。
如果不工作的话,我怀疑一个异常被抛出在触发事件的代码,或分配的财产,你应该寻找。
有似乎是你正在调用来改变一个线程不是UI线程值的可能性。如果是这样的话,那么你要么当元帅的呼叫火灾UI线程的属性更改事件,或进行更改到UI线程上的值。
当一个对象绑定到UI元素,更改对象可影响UI必须被UI线程上进行。