WPF TriState图像按钮

时间:2010-03-22 11:55:35

标签: wpf image button

有没有人有任何关于创建三态图像按钮的指针?

我有以下内容,但我真正想做的是拥有一个具有多个ImageSource属性的控件,如<Controls.TristateButton Image="" HoverImage="" PressedImage="" />

<Style TargetType="{x:Type Button}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <StackPanel Orientation="Horizontal" >
                    <Image Name="PART_Image" Source="path to normal image" />
                </StackPanel>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Source" Value="path to mouse over image" TargetName="PART_Image"/>
                    </Trigger>
                    <Trigger Property="IsPressed" Value="True">
                        <Setter Property="Source" Value="path to pressed image" TargetName="PART_Image"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

3 个答案:

答案 0 :(得分:18)

我自己遇到了同样的问题。我在这里创建了一个开源项目http://imagebuttonwpf.codeplex.com,您可以在其中获取最新版本的图像按钮。 我不喜欢“接受”的解决方案有几个原因(虽然它是一个更轻的解决方案,并有自己的优势)

  

Blockquote此StackOverflow问题的已接受答案显示了一种简单的方法:WPF - How to create image button with template

主要是我认为对于您想要更改图像的每个按钮覆盖控件模板是不正确的,因此我创建了一个名为ImageButton的自定义控件。它从按钮扩展,以便具有任何功能(尽管它可以从内容控件中轻松扩展),但也包含一个可以设置样式而无需重写整个控件模板的图像。 我不喜欢每次为我的按钮重写整个控件模板的另一个原因是我的基本按钮样式包含几个边框和鼠标悬停的动画效果,按下等等。每次重写这些都显然有自己的冗余问题。 无论如何这里是ImageButton类

public class ImageButton : Button
{
static ImageButton() {
  DefaultStyleKeyProperty.OverrideMetadata(typeof(ImageButton), new FrameworkPropertyMetadata(typeof(ImageButton)));
}

#region Dependency Properties

public double ImageSize
{
  get { return (double)GetValue(ImageSizeProperty); }
  set { SetValue(ImageSizeProperty, value); }
}

public static readonly DependencyProperty ImageSizeProperty =
    DependencyProperty.Register("ImageSize", typeof(double), typeof(ImageButton),
    new FrameworkPropertyMetadata(30.0, FrameworkPropertyMetadataOptions.AffectsRender, ImageSourceChanged));

public string NormalImage
{
  get { return (string)GetValue(NormalImageProperty); }
  set { SetValue(NormalImageProperty, value); }
}

public static readonly DependencyProperty NormalImageProperty =
    DependencyProperty.Register("NormalImage", typeof(string), typeof(ImageButton),
    new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.AffectsRender,ImageSourceChanged));

public string HoverImage
{
  get { return (string)GetValue(HoverImageProperty); }
  set { SetValue(HoverImageProperty, value); }
}

public static readonly DependencyProperty HoverImageProperty =
    DependencyProperty.Register("HoverImage", typeof(string), typeof(ImageButton),
    new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.AffectsRender, ImageSourceChanged));

public string PressedImage
{
  get { return (string)GetValue(PressedImageProperty); }
  set { SetValue(PressedImageProperty, value); }
}

public static readonly DependencyProperty PressedImageProperty =
    DependencyProperty.Register("PressedImage", typeof(string), typeof(ImageButton),
    new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.AffectsRender, ImageSourceChanged));

public string DisabledImage
{
  get { return (string)GetValue(DisabledImageProperty); }
  set { SetValue(DisabledImageProperty, value); }
}

public static readonly DependencyProperty DisabledImageProperty =
    DependencyProperty.Register("DisabledImage", typeof(string), typeof(ImageButton),
    new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.AffectsRender, ImageSourceChanged));

private static void ImageSourceChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
  Application.GetResourceStream(new Uri("pack://application:,,," + (string) e.NewValue));
}

#endregion

接下来,我们需要为我们的按钮提供一个默认控制模板,我已经将大部分边框等取出了这个,第一个,这样你就可以看到它在我们所有的样式中都被继承了

<ControlTemplate x:Key="ImageButtonTemplate" TargetType="{x:Type Controls:ImageButton}">   
<Grid x:Name="Grid">
  <Border x:Name="Background" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="3" />
  <StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center">
    <Image x:Name="ButtonImage" Source="{Binding NormalImage, RelativeSource={RelativeSource TemplatedParent}}" 
           Height="{Binding ImageSize, RelativeSource={RelativeSource TemplatedParent}}" 
           Width="{Binding ImageSize, RelativeSource={RelativeSource TemplatedParent}}"/>
    <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" RecognizesAccessKey="True" />
  </StackPanel>      
</Grid>
<ControlTemplate.Triggers>
  <Trigger Property="IsMouseOver" Value="true">
    <Setter TargetName="ButtonImage" Property="Source" Value="{Binding HoverImage, RelativeSource={RelativeSource TemplatedParent}}" />
  </Trigger>
  <Trigger Property="IsPressed" Value="true">
    <Setter TargetName="ButtonImage" Property="Source" Value="{Binding PressedImage, RelativeSource={RelativeSource TemplatedParent}}" />
  </Trigger>
  <Trigger Property="IsEnabled" Value="false">
    <Setter TargetName="ButtonImage" Property="Source" Value="{Binding DisabledImage, RelativeSource={RelativeSource TemplatedParent}}" />
  </Trigger>
</ControlTemplate.Triggers>

然后我们当然需要新图像按钮的默认样式

<Style TargetType="{x:Type Controls:ImageButton}" BasedOn="{x:Null}">
<Setter Property="Template" Value="{StaticResource ImageButtonTemplate}" />
</Style>

当然使用这种方法的好处我创建了一种基于父样式的样式,它使用Setter来改变依赖属性(而不是需要覆盖控件模板 - 目标)

<Style x:Key="TestImageButton" TargetType="{x:Type Controls:ImageButton}" BasedOn="{StaticResource {x:Type Controls:ImageButton}}">
<Setter Property="NormalImage" Value="/ImageButton;component/Resources/clear.png"/>
<Setter Property="HoverImage"  Value="/ImageButton;component/Resources/clear_green.png" />
<Setter Property="PressedImage" Value="/ImageButton;component/Resources/clear_darkgreen.png" />
<Setter Property="DisabledImage" Value="/ImageButton;component/Resources/clear_grey.png" />
</Style>

最后这意味着可以用几种不同的方式声明按钮,或者在XAML中声明图像路径

<Controls:ImageButton 
    Content="Test Button 1" 
    NormalImage="/ImageButton;component/Resources/edit.png"
    HoverImage="/ImageButton;component/Resources/edit_black.png"
    PressedImage="/ImageButton;component/Resources/edit_darkgrey.png"
    DisabledImage="/ImageButton;component/Resources/edit_grey.png"/>

或者使用风格

  <Controls:ImageButton 
    Content="Test Button 2"
    Style="{DynamicResource TestImageButton}"/>

希望有所帮助

答案 1 :(得分:3)

理想情况下,您必须创建一个继承自Button的自定义控件。添加三个依赖项属性,并为新控件创建默认样式。

您可以查看FluidKit库中的ImageButton课程 - 它完全符合您的要求。

答案 2 :(得分:3)

此StackOverflow问题的已接受答案显示了一种简单的方法: WPF - How to create image button with template

您可以在IsEnabled和IsPressed属性上创建属性触发器,并根据需要显示或隐藏图像。

正如Avanka在回答中指出的那样,你需要创建依赖属性来设置图像的路径。