【问题标题】:WPF : give me a best way for icon buttonWPF:给我一个图标按钮的最佳方式
【发布时间】:2011-10-18 16:32:11
【问题描述】:

我们可以使用如下代码的控件模板轻松制作图标按钮:

<Style x:Key="IconButton" TargetType="{x:Type Button}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate>
                <Grid>
                    <Image x:Name="Background" Source="/UOC;component/TOOLBAR_BUTTON_NORMAL.png"/>
                    <Image Source="/UOC;component/ICON_SLICER.gif" Width="20" Height="20" Margin="0,-10,0,0"/>
                    <TextBlock Foreground="White" FontSize="9" Text="{TemplateBinding Button.Content}" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,15,0,0"/>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="Button.IsMouseOver" Value="True">
                        <Setter Property="Source" TargetName="Background" Value="/UOC;component/TOOLBAR_BUTTON_OVER.png"/>
                        <Setter Property="Cursor" Value="Hand"/>
                    </Trigger>
                    <Trigger Property="Button.IsPressed" Value="True">
                        <Setter Property="Source" TargetName="Background" Value="/UOC;component/TOOLBAR_BUTTON_CLICK.png"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

但我认为这在实践中并不是一种有效的方式。因为我无法为每个图标按钮制作多种样式。 (例如,假设 App 中有三个按钮:“打开”按钮、“关闭”按钮和“导航”按钮。这些按钮具有不同的图标集。我无法制作像“IconButton_Close”、“IconButton_Open”、“IconButton_Nav”这样的样式. 这太愚蠢了。)

UserControl 可能是一个答案。但我认为这不是一个聪明的方法。因为如果我制作 UserControl,它将只是 Button 控件的包装。这不是正确的方法。

所以,给我一个图标按钮的最佳方式。

谢谢。

【问题讨论】:

    标签: wpf templates button icons


    【解决方案1】:

    这样做的正确方法是定义一个自定义按钮类,如下所示:

        public class MyButton : Button 
        {
            static MyButton() 
            {
                DefaultStyleKeyProperty.OverrideMetadata(typeof(MyButton), new FrameworkPropertyMetadata(typeof(MyButton)));
            }
    
            public static readonly DependencyProperty ImageSourceProperty = DependencyProperty.Register("ImageSource", typeof(ImageSource),
                typeof(MyButton), new FrameworkPropertyMetadata(null));
    
            public ImageSource ImageSource 
            {
                get { return (ImageSource)GetValue(ImageSourceProperty); }
                set { SetValue(ImageSourceProperty, value); }
            }
    
            public static readonly DependencyProperty ImageSourceHoverProperty = DependencyProperty.Register("ImageSourceHover", typeof(ImageSource),
                typeof(MyButton), new FrameworkPropertyMetadata(null));
    
            public ImageSource ImageSourceHover 
            {
                get { return (ImageSource)GetValue(ImageSourceHoverProperty); }
                set { SetValue(ImageSourceHoverProperty, value); }
            }
    
            public static readonly DependencyProperty ImageSourcePressedProperty = DependencyProperty.Register("ImageSourcePressed", typeof(ImageSource),
                typeof(MyButton), new FrameworkPropertyMetadata(null));
    
            public ImageSource ImageSourcePressed 
            {
                get { return (ImageSource)GetValue(ImageSourcePressedProperty); }
                set { SetValue(ImageSourcePressedProperty, value); }
            }
    
        }
    

    然后像这样定义默认样式:

    <Style x:Key="{x:Type local:MyButton}" TargetType="{x:Type local:MyButton}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:MyButton}">
                    <Grid>
                        <Image x:Name="Background" Source="{TemplateBinding ImageSource}" />
                        <Image Source="/UOC;component/ICON_SLICER.gif" Width="20" Height="20" Margin="0,-10,0,0"/>
                        <TextBlock Foreground="White" FontSize="9" Text="{TemplateBinding Button.Content}" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,15,0,0"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="Button.IsMouseOver" Value="True">
                            <Setter Property="Source" TargetName="Background" Value="{TemplateBinding ImageSourceHover}"/>
                            <Setter Property="Cursor" Value="Hand"/>
                        </Trigger>
                        <Trigger Property="Button.IsPressed" Value="True">
                            <Setter Property="Source" TargetName="Background" Value="{TemplateBinding ImageSourcePressed}"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    

    你会这样使用它:

    <local:MyButton ImageSource="/UOC;component/TOOLBAR_BUTTON_NORMAL.png"
        ImageSourceHover="/UOC;component/TOOLBAR_BUTTON_OVER.png"
        ImageSourcePressed="/UOC;component/TOOLBAR_BUTTON_CLICK.png" />
    

    【讨论】:

    【解决方案2】:

    不久前,我使用 TemplatePart 属性为自定义控件做了类似的事情。这会在面板中显示一个图标和一些文本。如果图标是错误或失败图标,它会将文本变为红色。有一个名为“Type”的依赖属性,它实际上只是没有扩展名的图像文件名。这是代码,我敢打赌,您可以将其调整为自定义按钮,您可以在其中设置源代码并仍然对模板进行自定义。

    [TemplatePart(Name = "PART_Image", Type = typeof(Image))]
    public class IconPanel : ContentControl
    {
        static IconPanel()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(IconPanel), new FrameworkPropertyMetadata(typeof(IconPanel)));
    }
    
    
    public string Type
    {
        get { return (string)GetValue(TypeProperty); }
        set { SetValue(TypeProperty, value); }
    }
    
    public static readonly DependencyProperty TypeProperty =
        DependencyProperty.Register("Type", typeof(string), typeof(IconPanel), 
        new UIPropertyMetadata("warning", TypeChangedCallback));
    
    static void TypeChangedCallback(DependencyObject obj, DependencyPropertyChangedEventArgs args)
    {
        IconPanel panel = obj as IconPanel;
        panel.UpdateImage();
    }
    
    void UpdateImage()
    {
        Image img = GetTemplateChild("PART_Image") as Image;
        if (img == null) return;
        string ImagePath = String.Format("pack://application:,,,/Resources/{0}.png", this.Type);
        Uri uri = new Uri(ImagePath, UriKind.RelativeOrAbsolute);
        BitmapImage bmp = new BitmapImage(uri);
        img.Source = bmp;
        if ( String.Compare(Type, "error", true) == 0 ||
            String.Compare(Type, "fail", true) == 0 )
        {
            this.Foreground = new SolidColorBrush(Color.FromRgb(0xFF, 0x00, 0x00));
        }
    }
    
    public override void OnApplyTemplate()
    {
        UpdateImage();
        base.OnApplyTemplate();
        }
    }
    

    XAML:

    <Style TargetType="{x:Type local:IconPanel}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type local:IconPanel}">
                        <Border Background="{TemplateBinding Background}"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}"
                                Padding="7">
                            <Grid Background="{TemplateBinding Background}">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="Auto"/>
                                    <ColumnDefinition Width="*"/>
                                </Grid.ColumnDefinitions>
                                    <Image
                                        x:Name="PART_Image"
                                        Margin="0,0,5,5"
                                        VerticalAlignment="Top"
                                        HorizontalAlignment="Left"
                                        Width="16" 
                                        Height="16" />
                                <ContentPresenter Grid.Column="1"/>
                            </Grid>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    

    【讨论】:

      猜你喜欢
      • 2012-10-27
      • 1970-01-01
      • 2012-10-22
      • 1970-01-01
      • 2015-10-03
      • 2020-04-26
      • 1970-01-01
      • 1970-01-01
      • 2011-08-23
      相关资源
      最近更新 更多