依赖项 属性 更改时未引发 WPF 事件
WPF Event Not Raised when Dependency Property Changed
我有以下基于 "heavy option" at this link 的自定义控件:
public partial class SelectableContentControl : ContentControl
{
public SelectableContentControl()
{
InitializeComponent();
var isCheckedDesc = DependencyPropertyDescriptor.FromProperty(IsCheckedProperty, typeof(SelectableContentControl));
isCheckedDesc.AddValueChanged(this, IsCheckedPropertyChanged);
}
public bool IsChecked
{
get { return (bool)GetValue(IsCheckedProperty); }
set { SetValue(IsCheckedProperty, value); }
}
public static readonly DependencyProperty IsCheckedProperty =
DependencyProperty.Register("IsChecked", typeof(bool),
typeof(SelectableContentControl), new PropertyMetadata(false));
private void IsCheckedPropertyChanged(object sender, EventArgs e)
{
var selectable = Content as IAmSelectable;
if (selectable != null) selectable.IsSelected = IsChecked;
}
}
为SelectableContentControl
定义的样式如下:
<Style TargetType="{x:Type controls1:SelectableContentControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type controls1:SelectableContentControl}">
<CheckBox IsChecked="{TemplateBinding IsChecked}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
...以及我的用法:
<controls:SelectableContentControl Grid.Row="2" Content="{Binding Dummy}" IsChecked="{Binding Dummy.IsChecked, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
我希望 IsCheckedPropertyChanged
在 UI 上的 IsChecked
值发生变化时被调用,但这并没有发生。有人看到我遗漏了什么吗?
TemplateBinding
在 OneWay
模式下工作,这意味着该值仅在源到目标方向上更新(您的控件是源,而 CheckBox
在模板目标)。如果您希望绑定在 TwoWay
模式下工作,您应该使用普通的 Binding
代替:
<ControlTemplate TargetType="{x:Type controls1:SelectableContentControl}">
<CheckBox IsChecked="{Binding IsChecked, RelativeSource={RelativeSource TemplatedParent}}" />
</ControlTemplate>
请注意,您不需要在绑定上指定Mode=TwoWay
,因为CheckBox.IsChecked
属性默认以双向模式绑定。
有关详细信息,请参阅 this question。
我有以下基于 "heavy option" at this link 的自定义控件:
public partial class SelectableContentControl : ContentControl
{
public SelectableContentControl()
{
InitializeComponent();
var isCheckedDesc = DependencyPropertyDescriptor.FromProperty(IsCheckedProperty, typeof(SelectableContentControl));
isCheckedDesc.AddValueChanged(this, IsCheckedPropertyChanged);
}
public bool IsChecked
{
get { return (bool)GetValue(IsCheckedProperty); }
set { SetValue(IsCheckedProperty, value); }
}
public static readonly DependencyProperty IsCheckedProperty =
DependencyProperty.Register("IsChecked", typeof(bool),
typeof(SelectableContentControl), new PropertyMetadata(false));
private void IsCheckedPropertyChanged(object sender, EventArgs e)
{
var selectable = Content as IAmSelectable;
if (selectable != null) selectable.IsSelected = IsChecked;
}
}
为SelectableContentControl
定义的样式如下:
<Style TargetType="{x:Type controls1:SelectableContentControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type controls1:SelectableContentControl}">
<CheckBox IsChecked="{TemplateBinding IsChecked}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
...以及我的用法:
<controls:SelectableContentControl Grid.Row="2" Content="{Binding Dummy}" IsChecked="{Binding Dummy.IsChecked, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
我希望 IsCheckedPropertyChanged
在 UI 上的 IsChecked
值发生变化时被调用,但这并没有发生。有人看到我遗漏了什么吗?
TemplateBinding
在 OneWay
模式下工作,这意味着该值仅在源到目标方向上更新(您的控件是源,而 CheckBox
在模板目标)。如果您希望绑定在 TwoWay
模式下工作,您应该使用普通的 Binding
代替:
<ControlTemplate TargetType="{x:Type controls1:SelectableContentControl}">
<CheckBox IsChecked="{Binding IsChecked, RelativeSource={RelativeSource TemplatedParent}}" />
</ControlTemplate>
请注意,您不需要在绑定上指定Mode=TwoWay
,因为CheckBox.IsChecked
属性默认以双向模式绑定。
有关详细信息,请参阅 this question。