我已经研究了以下情况很多小时了:我有一个xaml定义的窗口,该窗口利用了具有某些依赖项属性的usercontrol(ToggleButton)。
窗口的基础视图模型包含一些布尔对象,这些布尔对象表示设备的状态(打开/关闭),而另一些对象则表示请求切换带有正/反侧翼的设备(将PLC连接到这些对象,并且通讯正常)。
因此,用户控件上有2个DP:
用于切换设备的设备(将模式OneWayToSource与 UpdateSourceTrigger.Explicit 绑定可以正常工作(向我表明,共享DataContext之类的基础很好,并且在任何地方都不会“中断”)。
但是,表示另一个DP的绑定(绑定模式为OneWay的设备状态)显示以下症状:
启动程序之前(PLC-)设备已关闭(false)
结果:DeviceState属性的默认值为false。 设备首次开机时称为Set (基础viewmodel对象更改为true,通过 PropertyChanged通知),并且DependencyPropertyChanged为 被正确调用。进一步切换到关闭/打开(false / true) 再次不会导致再次调用“ set”(尽管 再次调用基础对象上的PropertyChanged。)
启动程序之前,设备已开启(true)
结果:DP处理程序在以下位置触发 程序的开始,没有更改 false或true可以再次调用它。
我已经尝试过追踪的内容是:
实现了 DummyDebugConverter 。
结果:我看到它也只被触发了一次。所以不再给我任何线索
分析“输出”窗口并找到以下消息:
System.Windows.Data信息:21:BindingExpression无法从空数据项检索值。当绑定分离或绑定到没有值的Nullable类型时,可能会发生这种情况。 BindingExpression:Path = bLightState.Value; DataItem ='ControlPanelModel'(HashCode = 45596481);目标元素是“ AdsButton”(名称=“ btnLight”);目标属性为“ DeviceState”(类型为“ Boolean”)
调试它并没有给我任何提示。我的断点在调试转换器或set方法中从未在任何地方向我显示空值。 viewmodel构造函数中的所有值均使用默认值初始化。但是我看到消息总是只有一次,我认为它与问题有某种联系。
除了我的用户控件之外,还对其他一些元素(标签和切换按钮)使用了相同的绑定表达式进行测试。它们工作得很好,并且只要视图模型中的对象发生更改(期望的行为),它们就会按预期更新其值。如果我删除用户控件,则会在2个分配器中显示该消息。
所以我得出的结论是,错误在于我对DP的定义。
以下是相关的代码段:
AdsButton.xaml.cs
[Description("When set to true the device is shown as on"), Category("Default")]
public bool DeviceState
{
get { return (bool)GetValue(DeviceStateProperty); }
set { SetValue(DeviceStateProperty, value); }
}
public static readonly DependencyProperty DeviceStateProperty =
DependencyProperty.Register(
"DeviceState", typeof(bool),
typeof(AdsButton),
new FrameworkPropertyMetadata(
false,
FrameworkPropertyMetadataOptions.None,
DeviceStateChanged,
CoerceDeviceStateProperty,
true,
UpdateSourceTrigger.Explicit));
private static void DeviceStateChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
(d as AdsButton).DeviceState = (bool) e.NewValue;
}
private static object CoerceDeviceStateProperty(DependencyObject d, object value)
{
return value ?? false;
}
ControlPanel.xaml
<src:AdsButton x:Name="btnLight"
Value="{Binding Path=bLight.Value, Mode=OneWayToSource}"
DeviceState="{Binding Path=bLightState.Value, Mode=OneWay}" />
<Label Content="{Binding bLightState.Value, Mode=OneWay}" />
<ToggleButton Content="Button" IsChecked="{Binding bLightState.Value, Mode=OneWay}" />
所以有人知道:为什么我自己的DP的反应与标准控件中的反应不同?
答案 0 :(得分:0)
由于罗杰(Roger)的最初评论,答案很明显:
使用setter方法设置DP本身会用固定值(有效地将其删除)覆盖绑定,但前提是新值与旧值不同。