【问题标题】:WPF Button Image only showing in last controlWPF 按钮图像仅显示在最后一个控件中
【发布时间】:2011-02-23 07:13:22
【问题描述】:

我对 WPF 相当陌生,可能在这里缺少一些简单的东西。如果我有 3 个控件,则只有最后一个控件会显示我指定的 OriginalImage。

任何帮助将不胜感激。谢谢 瑞恩

主窗口

<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 简化为更简单的东西,例如具有三个 ListButtons 的 StackPanel。
  • 如果你有一张它可以工作,如果你有5张,第5张图片将是显示的那张。我尝试只使用堆栈面板并得到相同的结果:(

标签: wpf image xaml button


【解决方案1】:

在你的风格中使用 x:Shared="False"

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

【讨论】:

    【解决方案2】:

    我将回答我自己的问题。 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>
    

    【讨论】:

      【解决方案3】:

      这是因为您为按钮设置了“切换”样式。您在那里使用的图像只创建一次(因为样式只评估一次)并且图像不能添加到多个按钮(在 WPF 中每个 Visual 只能有一个父级)。因此,您应用该样式的最后一个 Button 将赢得并窃取上一个按钮的图像。

      如果您想修改 VisualTree 的样式,您应该在 ControlTemplate 中执行此操作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-02-18
        • 2015-10-13
        • 2023-03-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多