WPF按钮图像仅在最后一个控件中显示

6

我对WPF还比较陌生,可能会忽略一些简单的东西。如果我有3个控件,只有最后一个控件会显示我指定的OriginalImage。

非常感谢任何帮助。谢谢 Ryan

主窗口

<Grid>

        <Grid.RowDefinitions>
            <RowDefinition Height="200*"/>
            <RowDefinition Height="60" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="85" />
            <ColumnDefinition Width="85" />
            <ColumnDefinition Width="85" />
            <ColumnDefinition Width="85" />
            <ColumnDefinition Width="300" />
        </Grid.ColumnDefinitions>

            <Grid Grid.Row="1">
                <but:ListButton OriginalImage="/CustomItemsPanel;component/ListBox/Images/add.png"
                            DisableImage="/CustomItemsPanel;component/ListBox/Images/addunselect.png"

            />
        </Grid  >
        <Grid Grid.Row="1" Grid.Column="1"  >
            <but:ListButton OriginalImage="/CustomItemsPanel;component/ListBox/Images/add.png"
                            DisableImage="/CustomItemsPanel;component/ListBox/Images/addunselect.png"

            />
        </Grid  >
        <Grid Grid.Row="1" Grid.Column="2"  >
            <but:ListButton OriginalImage="/CustomItemsPanel;component/ListBox/Images/add.png"
                            DisableImage="/CustomItemsPanel;component/ListBox/Images/addunselect.png"

            />
        </Grid>
</Grid>

控制 XAML

<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CustomItemsPanel.ListButton">

<LinearGradientBrush x:Key="ButtonBackground"  EndPoint="0.5,1" StartPoint="0.5,0">
    <LinearGradientBrush.GradientStops>
        <GradientStop Color="#FF0E3D70"/>
        <GradientStop Color="#FF001832" Offset="1"/>
    </LinearGradientBrush.GradientStops>
</LinearGradientBrush>

<LinearGradientBrush x:Key="ButtonBackgroundMouseOver"  EndPoint="0.5,1" StartPoint="0.5,0">
    <LinearGradientBrush.GradientStops>
        <GradientStop Color="#FF1E62A1" />
        <GradientStop Color="#FF0A3C6D" Offset="1"/>
    </LinearGradientBrush.GradientStops>
</LinearGradientBrush>

<LinearGradientBrush x:Key="ButtonBackgroundSelected"  EndPoint="0.5,1" StartPoint="0.5,0">
    <LinearGradientBrush.GradientStops>
        <GradientStop Color="Red" />
        <GradientStop Color="#FF0A2A4C" Offset="1"/>
    </LinearGradientBrush.GradientStops>
</LinearGradientBrush>

<Style x:Key="Toggle" TargetType="{x:Type Button}">
    <Setter Property="Content">
        <Setter.Value>
            <Image>
                <Image.Style>
                    <Style TargetType="{x:Type Image}">
                        <Setter Property="Source" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ListButton}}, Path=OriginalImage}"/>
                        <Style.Triggers>
                            <Trigger Property="IsEnabled" Value="False">
                                <Setter Property="Source" Value="{Binding Path=DisableImage, RelativeSource={RelativeSource TemplatedParent}}"/>
                            </Trigger>
                        </Style.Triggers>
                    </Style>
                </Image.Style>
            </Image>
        </Setter.Value>
    </Setter>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Grid Cursor="Hand">
                        <Border Name="back" Margin="0,1,0,0" Background="{StaticResource ButtonBackground}">
                        <ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center" x:Name="content" />

                    </Border>
                        <Border BorderThickness="1" BorderBrush="#FF004F92">
                            <Border BorderThickness="0,0,1,0" BorderBrush="#FF101D29" />
                        </Border>
                    </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True" >
                        <Setter TargetName="back" Property="Background" Value="{StaticResource ButtonBackgroundMouseOver}"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<Style TargetType="{x:Type local:ListButton}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:ListButton}">
                <Button Style="{StaticResource Toggle}" />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

</ResourceDictionary>

控制代码后置

public class ListButton :  Control
{
    public static readonly DependencyProperty MouseOverImageProperty;  
    public static readonly DependencyProperty OriginalImageProperty;
    public static readonly DependencyProperty DisableImageProperty;  

    static ListButton() {

        DefaultStyleKeyProperty.OverrideMetadata(typeof(ListButton), new FrameworkPropertyMetadata(typeof(ListButton)));

        MouseOverImageProperty = DependencyProperty.Register("MouseOverImage", typeof(ImageSource), typeof(ListButton), new UIPropertyMetadata(null));
        OriginalImageProperty = DependencyProperty.Register("OriginalImage", typeof(ImageSource), typeof(ListButton), new UIPropertyMetadata(null));
        DisableImageProperty = DependencyProperty.Register("DisableImage", typeof(ImageSource), typeof(ListButton), new UIPropertyMetadata(null));  
    }  

    public ImageSource MouseOverImage {  
        get { return (ImageSource)GetValue(MouseOverImageProperty); }  
        set { SetValue(MouseOverImageProperty, value); }  
    }  

    public ImageSource OriginalImage {  
        get { return (ImageSource)GetValue(OriginalImageProperty); }  
        set { SetValue(OriginalImageProperty, value); }  
    }

    public ImageSource DisableImage
    {
        get { return (ImageSource)GetValue(DisableImageProperty); }
        set { SetValue(DisableImageProperty, value); }
    }  
}

它真的总是只有最后一个有效吗?如果你只有一个,它有效;如果你有五个,只有第五个有效吗?虽然XAML看起来非常简单,但我的第一步调试可能是将该XAML简化为更简单的内容,比如只有三个ListButton的StackPanel。 - RwwL
如果你只有一个,它可以工作;如果你有5个,则第5个图像将被显示。我尝试使用StackPanel,但结果相同 :( - Ryan
3个回答

14

这是由于您的按钮“Toggle”样式导致的。您在其中使用的图像仅创建一次(因为样式仅评估一次),并且该图像无法添加到多个按钮中(在WPF中,每个Visual只能有一个父项)。因此,您应用样式到的最后一个按钮获胜并从前一个按钮中窃取了图像。

如果要在样式中修改VisualTree,您应该在ControlTemplate中完成。


10

我将回答自己的问题。Bitbonk给出了一个很好的解释,说明我做错了什么以及样式如何工作。谢谢!

 <Style x:Key="Toggle" TargetType="{x:Type Button}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Grid Cursor="Hand">
                    <Border Name="back" Margin="0,1,0,0" Background="{StaticResource ButtonBackground}">
                        <Image Name="imgBut" Source="{Binding Path=(OriginalImage), RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ListButton}}}" />
                    </Border>
                    <Border BorderThickness="1" BorderBrush="#FF004F92">
                        <Border BorderThickness="0,0,1,0" BorderBrush="#FF101D29" />
                    </Border>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True" >
                        <Setter TargetName="back" Property="Background" Value="{StaticResource ButtonBackgroundMouseOver}"/>
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="False" >
                        <Setter TargetName="imgBut" Property="Source" Value="{Binding Path=(DisableImage), RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ListButton}}}" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

0

在你的样式上使用x:Shared="False"

<Style x:Key="Toggle" x:Shared="False" TargetType="{x:Type Button}">
    ......
</Style>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接