属性 的绑定 DependencyProperty 是子样式 ComboBox

Binding DependencyProperty for property is substyle ComboBox

我有一个继承自 ComboBox 的 CustomComboBox 组件,其样式已复制到另一个资源字典 xaml 文件。

问题是,我能否或如何从 ComboBoxToggleButton 中使用的 ComboBoxTemplate 中使用的 CustomComboBoxStyle 中使用的子样式绑定 属性?

属性是:GryphlBrush
<路径x:Name="arrow" Stroke="{Binding GryphlBrush}" ...

下面的代码示例:

<Style x:Key="ComboBoxToggleButton" TargetType="{x:Type ToggleButton}">
    <!-- ... -->
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ToggleButton}">
                Border x:Name="templateRoot" SnapsToDevicePixels="true" Background="Transparent" BorderThickness="0" BorderBrush="Transparent" CornerRadius="4">
                    <Border x:Name="splitBorder" Width="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" SnapsToDevicePixels="true" Margin="0" HorizontalAlignment="Right" BorderThickness="1" BorderBrush="Transparent">
                        <Path x:Name="arrow" Stroke="{Binding GryphlBrush}" VerticalAlignment="Center" Margin="0" HorizontalAlignment="Center" Fill="{StaticResource ComboBox.Static.Glyph}" Data="F1 M 0,0 L 2.667,2.66665 L 5.3334,0 L 5.3334,-1.78168 L 2.6667,0.88501 L0,-1.78168 L0,0 Z"/>
                    </Border>
                </Border>
                <!-- ... -->
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<ControlTemplate x:Key="ComboBoxTemplate" TargetType="{x:Type ComboBox}">
    <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="4">
        <Grid x:Name="templateRoot" SnapsToDevicePixels="true">
            <!-- ... -->
            <ToggleButton x:Name="toggleButton" BorderBrush="Transparent" BorderThickness="0" Background="Transparent" Grid.ColumnSpan="2" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Style="{StaticResource ComboBoxToggleButton}"/>
            <!-- ... -->
        </Grid>
    </Border>
    <!-- ... -->
</ControlTemplate>

<Style x:Key="BorderedComboBoxStyles" TargetType="{x:Type components:BorderedComboBox}">
    <Setter Property="Template" Value="{StaticResource ComboBoxTemplate}"/>
</Style>

在后面的代码中,我只定义了依赖项 属性、getter 和 setter:

public class BorderedComboBox : ComboBox
{
    public static readonly DependencyProperty GryphlBrushDP = DependencyProperty.Register(
        "GryphlBrush", typeof(Brush), typeof(BorderedComboBox));
    
    private Brush _gryphlBrush;
    
    public Brush GryphlBrush
    {
        get => _gryphlBrush;
        set => _gryphlBrush = value;
    }
}

您应该遵守 naming conventions for dependency properties and their getters and setters. Furthermore using nameof 因为 属性 可以防止重命名时出错。

The name of the identifier field that you use to store the name and characteristics of the dependency property must be the Name you chose for the dependency property as part of the Register call, appended by the literal string Property. [...]

If you fail to follow this naming pattern, designers might not report your property correctly, and certain aspects of property system style application might not behave as expected.

因此您的依赖项 属性 定义应如下所示:

public class BorderedComboBox : ComboBox
{
   public static readonly DependencyProperty GryphlBrushProperty = DependencyProperty.Register(
      nameof(GryphlBrush), typeof(Brush), typeof(BorderedComboBox));

   private Brush _gryphlBrush;

   public Brush GryphlBrush
   {
      get => _gryphlBrush;
      set => _gryphlBrush = value;
   }
}

如果要绑定 GryphlBrush 属性,在 ToggleButton 控件模板中,您可以:

  • 创建自定义切换按钮并向其添加依赖项 属性,然后将其绑定到 BorderedComboBox 上的 GryphlBrush 属性。

  • 如果切换按钮仅在组合框中的此上下文中使用,请应用 RelativeSourceAncestorType 绑定,因为 BorderedComboBox 是父项切换按钮。

    <Style x:Key="ComboBoxToggleButton" TargetType="{x:Type ToggleButton}">
       <!--...-->
       <Setter Property="Template">
          <Setter.Value>
             <ControlTemplate TargetType="{x:Type ToggleButton}">
                <Border x:Name="templateRoot" SnapsToDevicePixels="true" Background="Transparent" BorderThickness="0" BorderBrush="Transparent" CornerRadius="4">
                <Border x:Name="splitBorder" Width="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" SnapsToDevicePixels="true" Margin="0" HorizontalAlignment="Right" BorderThickness="1" BorderBrush="Transparent">
                   <!--<Path x:Name="arrow" Stroke="{Binding GryphlBrush, RelativeSource={RelativeSource AncestorType={x:Type local:BorderedComboBox}}}" VerticalAlignment="Center" Margin="0" HorizontalAlignment="Center" Fill="{StaticResource ComboBox.Static.Glyph}" Data="F1 M 0,0 L 2.667,2.66665 L 5.3334,0 L 5.3334,-1.78168 L 2.6667,0.88501 L0,-1.78168 L0,0 Z"/>-->
                   <Path x:Name="arrow" Stroke="{Binding GryphlBrush, RelativeSource={RelativeSource AncestorType={x:Type local:BorderedComboBox}}}" VerticalAlignment="Center" Margin="0" HorizontalAlignment="Center" Data="F1 M 0,0 L 2.667,2.66665 L 5.3334,0 L 5.3334,-1.78168 L 2.6667,0.88501 L0,-1.78168 L0,0 Z"/>
                </Border>
                </Border>
                <!--...-->
             </ControlTemplate>
          </Setter.Value>
       </Setter>
    </Style>