WPF: дайте мне лучший способ для кнопки со значком - PullRequest
0 голосов
/ 03 августа 2011

Мы можем легко сделать значок кнопки с помощью шаблона элемента управления, например, следующего кода:

<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>

Но я думаю, что на практике это неэффективно.потому что я не могу сделать несколько стилей для каждой из кнопок значков.(например, давайте предположим, что в приложении три кнопки: кнопка «Открыть», «Закрыть» и «Навигация». Эти кнопки имеют разные наборы значков. Я не могу создавать такие стили, как «IconButton_Close», «IconButton_Open», «IconButton_Nav»).. это слишком глупо.)

UserControl может быть ответом.но я думаю, что это не умный способ для этого.потому что если я сделаю UserControl, это будет просто оболочка элемента управления Button.это не правильный путь.

Итак, дайте мне лучший способ для значка кнопки.

спасибо.

Ответы [ 2 ]

5 голосов
/ 03 августа 2011

Правильный способ сделать это - определить собственный класс кнопок, например:

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" />
0 голосов
/ 03 августа 2011

Некоторое время назад я сделал нечто подобное для пользовательского элемента управления, используя атрибут TemplatePart.Это отображает значок и некоторый текст на панели.Если значки означают ошибку или ошибку, текст становится красным.Существует свойство зависимости, называемое «Тип», которое на самом деле является просто именем файла изображения без расширения.Вот код, могу поспорить, что вы можете адаптировать его для пользовательской кнопки, где вы можете установить источник и при этом сохранить настройки для шаблона.

[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>
...