如何使用XAML使BorderThickness,BorderBrush值传播给所有子节点

时间:2016-01-06 14:52:16

标签: wpf

如果我在Window代码中设置了FontFamilyFontSize属性,请在我的XAML中。他们影响所有的孩子。所有控件现在都具有相同的FontFamily和FontSize。但是,如果同样设置BorderThicknessBorderBrush,则只有我的Window受到影响。其余的儿童控制措施不会产生任何影响。

我希望我的所有孩子控制窗口中的BorderThicknessBorderColor属性与FontFamilyFontSize相同。

EG;

<Window
   ...        
 FontFamily="Segoe Print" FontSize="24">

    <Canvas Margin="50" Background="Wheat">
        <Grid Margin="15" Background="AliceBlue">
            <Button Margin="5" Content="Press"/>
        </Grid>
        <Label Canvas.Left="178" Canvas.Top="10" Background="AliceBlue">
            <TextBlock Text="some text"/>
        </Label>
        <Border Canvas.Left="62" Canvas.Top="128"  Background="Azure" Height="68" Width="181">
            <CheckBox Content="CheckBox" Margin="10,10,16,22"/>
        </Border>
    </Canvas>

</Window>

上面的代码将以“Segoe Print”字体显示所有控件,字体大小为24.

但是如果我在Window标签中设置BorderThickness和BorderBrush,则只会影响Window而不是所有孩子。

我可以使用代码处理Loaded event,使用Binding,当然还可以使用全局Style定位Border来实现此效果。但我想在没有它们的情况下这样做,因为我希望该属性能够如上所述自动传播。

期望效果: 当我将Control拖到我的Designer表面上时,拖动的Control应该根据Window中的设置更新其BorderThickness和BorderBrush属性。如果无法使用默认行为,那么我怎样才能至少实现在窗口中设置属性并让所有孩子对其做出反应的效果。

注意:我不想使用Style,但想要使用property value inheritanceProperty Value Inheritance

2 个答案:

答案 0 :(得分:0)

终于实现了我想要实现的目标。请参阅下面的代码。在Window中设置两个附加属性,现在如果在设计器上拖动控件,并且这些控件显示与边框相关的属性,则更改立即可见。

<Window ...
   local:InheritableProps.BorderThickness="5.0"
   local:InheritableProps.BorderBrush="Yellow"
>

    <Canvas Margin="50" Background="Wheat">
        <Border Canvas.Left="60" Canvas.Top="103" Width="75">
            <Button Content="Button" Height="22" Margin="5"/>  
        </Border>
        <Label Canvas.Left="177" Canvas.Top="84" Height="55" Width="143">
            <TextBox Height="23" TextWrapping="Wrap" Text="TextBox" Width="120"/>
        </Label>
    </Canvas>

</Window>

我写了两个附加属性,类似于TextElement.FontSize。为了启用PropertyValueInheritance,我使用了FrameworkPropertyMetadataOptions.Inherits选项。在相应的PropertyChangedHandlers中,我检查Object是否公开了边框属性,然后使用SetCurrentValue方法更改它们。直接分配或使用SetValue方法将更改本地值。本地值具有最高优先级,这里我们仅尝试继承属性值。

public class InheritableProps : DependencyObject
{
    public static Thickness GetBorderThickness(DependencyObject obj)
    {
        return (Thickness)obj.GetValue(BorderThicknessProperty);
    }

    public static void SetBorderThickness(DependencyObject obj, Thickness value)
    {
        obj.SetValue(BorderThicknessProperty, value);
    }

    // Using a DependencyProperty as the backing store for BorderThickness.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty BorderThicknessProperty =
        DependencyProperty.RegisterAttached("BorderThickness", typeof(Thickness), typeof(InheritableProps),
                    new FrameworkPropertyMetadata(new Thickness(), FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.Inherits,
                        new PropertyChangedCallback(BorderThicknessCallback),
                        null));

    public static SolidColorBrush GetBorderBrush(DependencyObject obj)
    {
        return (SolidColorBrush)obj.GetValue(BorderBrushProperty);
    }

    public static void SetBorderBrush(DependencyObject obj, SolidColorBrush value)
    {
        obj.SetValue(BorderBrushProperty, value);
    }

    // Using a DependencyProperty as the backing store for BorderBrush.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty BorderBrushProperty =
        DependencyProperty.RegisterAttached("BorderBrush", typeof(SolidColorBrush), typeof(InheritableProps),
                        new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.Inherits, 
                        new PropertyChangedCallback(BorderBrushCallback),
                        null));

    private static void BorderBrushCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        Debug.WriteLine("BorderBrush > " + d.ToString());

        Type type = d.GetType();
        PropertyInfo borderBrushPropInfo = type.GetProperty("BorderBrush");
        PropertyInfo borderThicknessPropInfo = type.GetProperty("BorderThickness");

        if (borderBrushPropInfo != null && borderThicknessPropInfo !=null)
        {
            d.SetCurrentValue(Border.BorderBrushProperty, e.NewValue);

            /* This will set the local value which has highest precedence*/
            //borderBrushPropInfo.SetValue(d, e.NewValue);
        }
    }

    private static void BorderThicknessCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        Debug.WriteLine("BorderThickness > " + d.ToString());

        Type type = d.GetType();
        PropertyInfo borderBrushPropInfo = type.GetProperty("BorderBrush");
        PropertyInfo borderThicknessPropInfo = type.GetProperty("BorderThickness");

        if (borderBrushPropInfo != null && borderThicknessPropInfo != null)
        {
            d.SetCurrentValue(Border.BorderThicknessProperty, e.NewValue);

            /* This will set the local value which has highest precedence*/
            //borderThicknessPropInfo.SetValue(d, e.NewValue);                
        }
    }        
}

答案 1 :(得分:-1)

<Window.Resources>
        <Style TargetType="Border">
            <Setter Property="VerticalAlignment" Value="Stretch" />
            <Setter Property="Margin" Value="3" />
            <Setter Property="BorderBrush" Value="SteelBlue" />
            <Setter Property="BorderThickness" Value="3,2.7,3,2.7" />
            <Setter Property="CornerRadius" Value="3" />
        </Style>