【问题标题】:WPF accesses only single instance of derived class with dependency propertyWPF 仅访问具有依赖属性的派生类的单个实例
【发布时间】:2016-03-24 18:33:10
【问题描述】:

我有一个从 Button 派生的简单类,具有依赖属性:

public sealed class CircleButton : Button
{
    public Visual Visual
    {
        get { return (Visual)GetValue(VisualProperty); }
        set { SetValue(VisualProperty, value); }
    }

    public static readonly DependencyProperty VisualProperty = DependencyProperty.Register("Visual", typeof(Visual), typeof(CircleButton));
}

CircleButton 的样式如下:

<Style x:Key="CircleButtonStyle" TargetType="{x:Type controls1:CircleButton}">
    ...
    <Setter Property="Content">
        <Setter.Value>
            <Rectangle Style="{StaticResource CircleButtonRectangleStyle}"/>
        </Setter.Value>
    </Setter>
    ...
</Style>

CircleButton样式中引用的矩形样式定义为:

<Style x:Key="CircleButtonRectangleStyle" TargetType="{x:Type Rectangle}">
    <Setter Property="Width" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type controls1:CircleButton}}, Path=Width, Converter={StaticResource ArithmeticConverter}}"/>
    <Setter Property="Height" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type controls1:CircleButton}}, Path=Height, Converter={StaticResource ArithmeticConverter}}"/>
    <Setter Property="Fill" Value="White"/>
    <Setter Property="OpacityMask">
        <Setter.Value>
            <VisualBrush Visual="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type controls1:CircleButton}}, Path=Visual}"/>
        </Setter.Value>
    </Setter>
</Style>

最后,我的 XAML 定义了三个 CircleButton 实例:

        <StackPanel Grid.Row="1" Grid.Column="2">
            <controls:CircleButton HorizontalAlignment="Center" VerticalAlignment="Center" Width="30.0" Height="30.0" 
                    Style="{DynamicResource CircleButtonStyle}" Command="{Binding Add}" ToolTip="Add new product filter." BorderBrush="White" BorderThickness="1" 
                                   Background="{DynamicResource AccentColorBrush}" Visual="{DynamicResource appbar_add}"/>
            <controls:CircleButton HorizontalAlignment="Center" VerticalAlignment="Center" Width="30.0" Height="30.0" 
                    Style="{DynamicResource CircleButtonStyle}" Command="{Binding Remove}" ToolTip="Remove product filter." BorderBrush="White" BorderThickness="1" 
                                   Background="{DynamicResource AccentColorBrush}" Visual="{DynamicResource appbar_minus}"/>
            <controls:CircleButton HorizontalAlignment="Center" VerticalAlignment="Center" Width="30.0" Height="30.0" 
                    Style="{DynamicResource CircleButtonStyle}" Command="{Binding Remove}" ToolTip="Remove product filter." BorderBrush="White" BorderThickness="1" 
                                   Background="{DynamicResource AccentColorBrush}" Visual="{DynamicResource appbar_music}"/>
        </StackPanel>

所有三个按钮都会显示,但只有序列中的最后一个有图像(它是正确的)。无论我添加多少按钮,都会发生这种情况。

有人知道我遗漏了什么以及我需要做些什么来纠正它吗?

【问题讨论】:

    标签: c# wpf xaml dependency-properties


    【解决方案1】:

    这并不明显,但实际上您只定义了一个VisualBrush 的实例。该Setter.Value 元素的内容将只有一份副本。每次它被添加到您的一个圆形按钮时,它都会被拉出前一个按钮。

    尝试应用模板,然后将该视觉画笔应用到模板中的元素。每次应用模板时,都会单独创建模板中的元素

    现在,您不能将ControlTemplate 应用于Rectangle。但是您可以将大量模板应用于很多事情,所以没什么大不了的。

    这可能有效。 ButtonContentControl 的子类,因此它有一个ContentTemplate 属性,它被实例化以显示您在ButtonContent 属性中放置的任何内容。这个用法有点搞笑,因为它不显示Content——但你没有使用Content

    <Style x:Key="CircleButtonStyle" TargetType="{x:Type controls1:CircleButton}">
        <!-- ... -->
        <Setter Property="ContentTemplate">
            <Setter.Value>
                <DataTemplate>
                    <Rectangle
                        Width="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type controls1:CircleButton}}, Path=Width, Converter={StaticResource ArithmeticConverter}}"
                        Height="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type controls1:CircleButton}}, Path=Height, Converter={StaticResource ArithmeticConverter}}"
                        Fill="White"
                        >
                        <Rectangle.OpacityMask>
                            <VisualBrush Visual="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type controls1:CircleButton}}, Path=Visual}"/>
                        </Rectangle.OpacityMask>
                    </Rectangle>
                </DataTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    

    但是你知道ContentControl.Content 是什么类型吗?这是Object。你可以把任何东西塞进去,ContentTemplate 可以用它找到的任何东西做任何它喜欢做的事情。我敢打赌这会很好用,并且可能完全不用编写 CircleButton 子类:

    <Style x:Key="CircleButtonStyle" TargetType="{x:Type Button}">
        <!-- ... -->
        <Setter Property="ContentTemplate">
            <Setter.Value>
                <DataTemplate>
                    <Rectangle
                        Width="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}, Path=Width, Converter={StaticResource ArithmeticConverter}}"
                        Height="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}, Path=Height, Converter={StaticResource ArithmeticConverter}}"
                        Fill="White"
                        >
                        <Rectangle.OpacityMask>
                            <VisualBrush Visual="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}, Path=Content}"/>
                        </Rectangle.OpacityMask>
                    </Rectangle>
                </DataTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    
    <!-- ... -->
    
    <Button 
        Style="{DynamicResource CircleButtonStyle}" 
        Command="{Binding Remove}" 
        ToolTip="Remove product filter." 
        Content="{DynamicResource appbar_music}"
        />
    

    【讨论】:

    • 谢谢,让我看看这个。 Rectangle 似乎不允许 ControlTemplate 定义,但也许有一种方法可以直接在 CircleButton 样式中执行此操作。
    • @ket 你不需要模板矩形。您模板化的内容项可以是任何可以模板化的内容,因为无论如何您都在替换它的内容。 ContentControl 会很好。
    • @ket 更新为 Style 可能会完成这项工作。
    • 太棒了 - 成功了!非常感谢。我本可以花很多时间来弄清楚这一点。
    • @ket 很高兴听到这个消息!
    猜你喜欢
    • 1970-01-01
    • 2018-03-21
    • 2012-08-06
    • 1970-01-01
    • 2011-04-21
    • 2020-03-28
    • 1970-01-01
    • 1970-01-01
    • 2021-12-04
    相关资源
    最近更新 更多