绑定到自定义控件的嵌套依赖属性
Binding to nested dependency properties of custom control
我有几个派生自 DockPanel、ToggleButton、ComboBox 等的自定义控件。我有一个 class Props
,我想在每个控件中用作依赖项 属性派生 classes。所有这些 classes 都需要具有相同的依赖属性(包含在 Props
中)并且可能有几个它们自己的独特属性(例如仅在停靠面板中)。
一个示例用例是属性 ExistsInConfig 和 RightVisible。我希望控件仅在两者都设置为 true 时才可见。这个逻辑应该在我所有的自定义派生控件中可用。
DockPanel.cs:
public class DockPanel : System.Windows.Controls.DockPanel
{
public DockPanel()
{
Props = new Props();
}
public Props Props
{
get
{
return (Props)GetValue(Properties);
}
set
{
SetValue(Properties, value);
}
}
public static readonly DependencyProperty Properties =
DependencyProperty.Register("Props", typeof(Props), typeof(DockPanel), new PropertyMetadata(null));
}
Props.cs:
public class Props: DependencyObject
{
public Props(){}
public bool RightVisible { get; set;}
public bool ExistsInConfig { get; set; }
public static readonly DependencyProperty RightVisibleProperty =
DependencyProperty.Register("RightVisible", typeof(bool), typeof(Props), new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public static readonly DependencyProperty ExistsInConfigProperty =
DependencyProperty.Register("ExistsInConfig", typeof(bool), typeof(Props), new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public static bool GetExistsInConfig(DependencyObject obj)
{
return (bool)obj.GetValue(ExistsInConfigProperty);
}
public static void SetExistsInConfig(DependencyObject obj, bool value)
{
obj.SetValue(ExistsInConfigProperty, value);
}
public static bool GetRightVisible(DependencyObject obj)
{
return (bool)obj.GetValue(RightVisibleProperty);
}
public static void SetRightVisible(DependencyObject obj, bool value)
{
obj.SetValue(RightVisibleProperty, value);
}
}
DockPanel 的样式:
<Style x:Key="CustomDockPanelStyle" TargetType="custom:DockPanel">
<Setter Property="Visibility">
<Setter.Value>
<MultiBinding Converter="{StaticResource MultipleBooleanToVisibilityConverter}">
<Binding RelativeSource="{RelativeSource Self}" Path="Props.ExistsInConfig" NotifyOnSourceUpdated="True" NotifyOnTargetUpdated="True" UpdateSourceTrigger="PropertyChanged"/>
<Binding RelativeSource="{RelativeSource Self}" Path="Props.RightVisible" NotifyOnSourceUpdated="True" NotifyOnTargetUpdated="True" UpdateSourceTrigger="PropertyChanged" />
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
使用XAML中的控件:
<Window.Resources>
<Style TargetType="{x:Type custom:DockPanel}" BasedOn={StaticResource CustomDockPanelStyle}"
</Window.Resources>
<custom:DockPanel
custom:Props.ExistsInConfig="{Binding ElementName=ToggleCombinedVisibility, Path=IsChecked, Mode=OneWay, NotifyOnTargetUpdated=True, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}"
custom:Props.RightVisible="{Binding ElementName=ToggleCombinedVisibility, Path=IsChecked, Mode=OneWay, NotifyOnTargetUpdated=True, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}">
<ToggleButton x:Name="ToggleCombinedVisibility" IsChecked="True" />
问题是,绑定不起作用。 MultipleBooleanToVisibilityConverter
只会在加载视图时被调用,而不是在我尝试使用按钮切换可见性时被调用。如果我在 RightVisible
和 ExistsInConfig
的 PropertyMetadata 中指定回调,它们会在切换按钮后被调用,但转换器不会。
我是否必须让 DockPanel 知道 Props
已更改?我该怎么做?我想不出在两个 class 上实现 INotifyPropertyChanged
的方法。
您 Style
中的绑定路径有误。
附加属性应该用括号括起来,自定义附加属性前面应该有命名空间别名。
这应该有效:
<Style x:Key="CustomDockPanelStyle" TargetType="custom:DockPanel">
<Setter Property="Visibility">
<Setter.Value>
<MultiBinding Converter="{StaticResource MultipleBooleanToVisibilityConverter}">
<Binding RelativeSource="{RelativeSource Self}" Path="(custom:Props.ExistsInConfig)" NotifyOnSourceUpdated="True" NotifyOnTargetUpdated="True" UpdateSourceTrigger="PropertyChanged"/>
<Binding RelativeSource="{RelativeSource Self}" Path="(custom:Props.RightVisible)" NotifyOnSourceUpdated="True" NotifyOnTargetUpdated="True" UpdateSourceTrigger="PropertyChanged" />
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
我有几个派生自 DockPanel、ToggleButton、ComboBox 等的自定义控件。我有一个 class Props
,我想在每个控件中用作依赖项 属性派生 classes。所有这些 classes 都需要具有相同的依赖属性(包含在 Props
中)并且可能有几个它们自己的独特属性(例如仅在停靠面板中)。
一个示例用例是属性 ExistsInConfig 和 RightVisible。我希望控件仅在两者都设置为 true 时才可见。这个逻辑应该在我所有的自定义派生控件中可用。
DockPanel.cs:
public class DockPanel : System.Windows.Controls.DockPanel
{
public DockPanel()
{
Props = new Props();
}
public Props Props
{
get
{
return (Props)GetValue(Properties);
}
set
{
SetValue(Properties, value);
}
}
public static readonly DependencyProperty Properties =
DependencyProperty.Register("Props", typeof(Props), typeof(DockPanel), new PropertyMetadata(null));
}
Props.cs:
public class Props: DependencyObject
{
public Props(){}
public bool RightVisible { get; set;}
public bool ExistsInConfig { get; set; }
public static readonly DependencyProperty RightVisibleProperty =
DependencyProperty.Register("RightVisible", typeof(bool), typeof(Props), new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public static readonly DependencyProperty ExistsInConfigProperty =
DependencyProperty.Register("ExistsInConfig", typeof(bool), typeof(Props), new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public static bool GetExistsInConfig(DependencyObject obj)
{
return (bool)obj.GetValue(ExistsInConfigProperty);
}
public static void SetExistsInConfig(DependencyObject obj, bool value)
{
obj.SetValue(ExistsInConfigProperty, value);
}
public static bool GetRightVisible(DependencyObject obj)
{
return (bool)obj.GetValue(RightVisibleProperty);
}
public static void SetRightVisible(DependencyObject obj, bool value)
{
obj.SetValue(RightVisibleProperty, value);
}
}
DockPanel 的样式:
<Style x:Key="CustomDockPanelStyle" TargetType="custom:DockPanel">
<Setter Property="Visibility">
<Setter.Value>
<MultiBinding Converter="{StaticResource MultipleBooleanToVisibilityConverter}">
<Binding RelativeSource="{RelativeSource Self}" Path="Props.ExistsInConfig" NotifyOnSourceUpdated="True" NotifyOnTargetUpdated="True" UpdateSourceTrigger="PropertyChanged"/>
<Binding RelativeSource="{RelativeSource Self}" Path="Props.RightVisible" NotifyOnSourceUpdated="True" NotifyOnTargetUpdated="True" UpdateSourceTrigger="PropertyChanged" />
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
使用XAML中的控件:
<Window.Resources>
<Style TargetType="{x:Type custom:DockPanel}" BasedOn={StaticResource CustomDockPanelStyle}"
</Window.Resources>
<custom:DockPanel
custom:Props.ExistsInConfig="{Binding ElementName=ToggleCombinedVisibility, Path=IsChecked, Mode=OneWay, NotifyOnTargetUpdated=True, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}"
custom:Props.RightVisible="{Binding ElementName=ToggleCombinedVisibility, Path=IsChecked, Mode=OneWay, NotifyOnTargetUpdated=True, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}">
<ToggleButton x:Name="ToggleCombinedVisibility" IsChecked="True" />
问题是,绑定不起作用。 MultipleBooleanToVisibilityConverter
只会在加载视图时被调用,而不是在我尝试使用按钮切换可见性时被调用。如果我在 RightVisible
和 ExistsInConfig
的 PropertyMetadata 中指定回调,它们会在切换按钮后被调用,但转换器不会。
我是否必须让 DockPanel 知道 Props
已更改?我该怎么做?我想不出在两个 class 上实现 INotifyPropertyChanged
的方法。
您 Style
中的绑定路径有误。
附加属性应该用括号括起来,自定义附加属性前面应该有命名空间别名。
这应该有效:
<Style x:Key="CustomDockPanelStyle" TargetType="custom:DockPanel">
<Setter Property="Visibility">
<Setter.Value>
<MultiBinding Converter="{StaticResource MultipleBooleanToVisibilityConverter}">
<Binding RelativeSource="{RelativeSource Self}" Path="(custom:Props.ExistsInConfig)" NotifyOnSourceUpdated="True" NotifyOnTargetUpdated="True" UpdateSourceTrigger="PropertyChanged"/>
<Binding RelativeSource="{RelativeSource Self}" Path="(custom:Props.RightVisible)" NotifyOnSourceUpdated="True" NotifyOnTargetUpdated="True" UpdateSourceTrigger="PropertyChanged" />
</MultiBinding>
</Setter.Value>
</Setter>
</Style>