В стиле WPF, как я могу изменить определенный цвет?

1

Я делаю кнопку Image/Text. Когда мышь над событием возникла, я хочу изменить цвет моей рисованной кисти. Как я могу это сделать? В приведенном ниже примере, я хочу, чтобы цвет значка, красный → Синий, когда мышь.

<SolidColorBrush x:Key="iconBrush" Color="Red"/>
<DrawingBrush x:Key="buttonIcon" Stretch="Uniform">
    <DrawingBrush.Drawing>
        <DrawingGroup>
            <DrawingGroup.Children>
                <GeometryDrawing Brush="{StaticResource iconBrush}" Geometry="... />
            </DrawingGroup.Children>
        </DrawingGroup>
    </DrawingBrush.Drawing>
</DrawingBrush>

<Style x:Key="ImageTextButtonStyle" TargetType="{x:Type Button}">
    ...
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Border>                        
                        <Grid>
                           <Grid.RowDefinitions>
                               <RowDefinition Height="20"/>
                               <RowDefinition Height="10"/>
                           </Grid.RowDefinitions>

                            <Grid Grid.Row="0" Background="{StaticResource buttonIcon}" />
                            <Grid Grid.Row="1">
                                <ContentPresenter ...
                                      />
                        </Grid>

                        </Grid>

                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter TargetName="{StaticResource iconBrush}" Value="Blue" />
                         ---> I Want to do this way..
Теги:
wpf
button
styles

2 ответа

2
Лучший ответ

невозможно напрямую, как вы пытаетесь достичь, поскольку вложенные свойства или установка значений ресурсов не поддерживаются в сеттерах

вот обходной путь

  • я переместил кисть рисования в фоновое свойство сетки
  • связанная кисть геометрии рисования кисти на фоне шаблона родителя, который является кнопкой
  • а затем переключить фон шаблона в триггере

вот код

<SolidColorBrush x:Key="iconBrush" Color="Red" />
<SolidColorBrush x:Key="blueBrush" Color="Blue" />
<Style x:Key="ImageTextButtonStyle" TargetType="{x:Type Button}">
    <Setter Property="Background" Value="{StaticResource iconBrush}" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Border>
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="20" />
                            <RowDefinition Height="10" />
                        </Grid.RowDefinitions>
                        <Grid Grid.Row="0">
                            <Grid.Background>
                                <DrawingBrush Stretch="Uniform">
                                    <DrawingBrush.Drawing>
                                        <DrawingGroup>
                                            <DrawingGroup.Children>
                                                <GeometryDrawing Brush="{Binding Background, RelativeSource={RelativeSource TemplatedParent}}" Geometry="..." />
                                            </DrawingGroup.Children>
                                        </DrawingGroup>
                                    </DrawingBrush.Drawing>
                                </DrawingBrush>
                            </Grid.Background>
                        </Grid>
                        <Grid Grid.Row="1">
                            <ContentPresenter />
                        </Grid>
                    </Grid>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Background" Value="{StaticResource blueBrush}" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Другой подход

  • Я определил 2 значка
  • установить один значок на фон сетки
  • переключиться на другой значок на основе триггера

код

<DrawingBrush x.Key="redIcon" Stretch="Uniform">
    <DrawingBrush.Drawing>
        <DrawingGroup>
            <DrawingGroup.Children>
                <GeometryDrawing Brush="Red" Geometry="..." />
            </DrawingGroup.Children>
        </DrawingGroup>
    </DrawingBrush.Drawing>
</DrawingBrush>

<DrawingBrush x.Key="blueIcon" Stretch="Uniform">
    <DrawingBrush.Drawing>
        <DrawingGroup>
            <DrawingGroup.Children>
                <GeometryDrawing Brush="Blue" Geometry="..." />
            </DrawingGroup.Children>
        </DrawingGroup>
    </DrawingBrush.Drawing>
</DrawingBrush>

<Style x:Key="ImageTextButtonStyle" TargetType="{x:Type Button}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Border>
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="20" />
                            <RowDefinition Height="10" />
                        </Grid.RowDefinitions>
                        <Grid Grid.Row="0" x:Name="icon" Background="{StaticResource redIcon}" />
                        <Grid Grid.Row="1">
                            <ContentPresenter />
                        </Grid>
                    </Grid>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Background" Value="{StaticResource blueIcon}" TargetName="icon" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Прикрепленное свойство для значка

класс для объявления свойства и сохранения значения

class Extras: DependencyObject
{
    public static Brush GetIcon(DependencyObject obj)
    {
        return (Brush)obj.GetValue(IconProperty);
    }

    public static void SetIcon(DependencyObject obj, Brush value)
    {
        obj.SetValue(IconProperty, value);
    }

    // Using a DependencyProperty as the backing store for Icon.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty IconProperty =
        DependencyProperty.RegisterAttached("Icon", typeof(Brush), typeof(Extras), new PropertyMetadata(null));
}

Ресурсы XAML

<DrawingBrush x:Key="buttonIcon"
                Stretch="Uniform">
    <DrawingBrush.Drawing>
        <DrawingGroup>
            <DrawingGroup.Children>
                <GeometryDrawing Brush="Red"
                                    Geometry="..." />
            </DrawingGroup.Children>
        </DrawingGroup>
    </DrawingBrush.Drawing>
</DrawingBrush>
<Style x:Key="ImageTextButtonStyle"
        TargetType="{x:Type Button}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Border>
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="20" />
                            <RowDefinition Height="10" />
                        </Grid.RowDefinitions>
                        <Grid Grid.Row="0"
                                Background="{TemplateBinding l:Extras.Icon}" />
                        <Grid Grid.Row="1">
                            <ContentPresenter />
                        </Grid>
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Применение

<Button Style="{StaticResource ImageTextButtonStyle}"
        Content="Icon Button"
        l:Extras.Icon="{StaticResource buttonIcon}"/>
  • 0
    Спасибо за ваш добрый ответ. но я не могу вставить кисть для рисования в стиль, я буду использовать этот стиль на нескольких кнопках, которые имеют разные изображения друг друга. Итак, я извлекаю класс Button, добавляю свойство icon icon и использую как <local: MyImageTextButton IconImage = "{StaticResource someIcon}" ...
  • 0
    Вывод - это своего рода победа над декларативной силой WPF, у вас все еще есть возможность использовать присоединенные свойства и присоединенное поведение даже для сложных решений. Вы можете достичь того же самого, даже не выводя, и это будет многократно используемое решение, если вы должны были повторно использовать подобную логику, например. Флажок или радио и т. Д.
Показать ещё 5 комментариев
0

Это может быть достигнуто довольно просто с помощью Attached Properties. Вы также можете переопределить класс Button, но я предпочитаю первое решение, так как вы только шаблоны существующего элемента управления. Кроме того, вы можете повторно использовать прикрепленное свойство с элементами управления, отличными от Button.

Прилагаемое свойство:

public class OnMouseOver : DependencyObject
{
    public static readonly DependencyProperty BackgroundProperty =
    DependencyProperty.RegisterAttached(
      "Background",
      typeof(Brush),
      typeof(OnMouseOver)
    );
    public static void SetBackground(UIElement element, Brush value)
    {
        element.SetValue(BackgroundProperty, value);
    }
    public static Brush GetBackground(UIElement element)
    {
        return (Brush)element.GetValue(BackgroundProperty);
    }
}

Часть XAML:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <Style x:Key="buttonBaseStyle" TargetType="Button">
            <Style.Setters>
                <Setter Property="Background" Value="Green" />
                <Setter Property="local:OnMouseOver.Background" Value="Lime" />
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="Button">
                            <Border Name="border" Background="{TemplateBinding Background}" CornerRadius="8" />
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsMouseOver" Value="True">
                                    <Setter TargetName="border" Property="Background" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(local:OnMouseOver.Background)}" />
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style.Setters>
        </Style>
        <Style x:Key="buttonRedStyle" TargetType="Button" BasedOn="{StaticResource buttonBaseStyle}">
            <Style.Setters>
                <Setter Property="Background" Value="Red" />
                <Setter Property="local:OnMouseOver.Background" Value="Pink" />
            </Style.Setters>
        </Style>
        <Style x:Key="buttonBlueStyle" TargetType="Button" BasedOn="{StaticResource buttonBaseStyle}">
            <Style.Setters>
                <Setter Property="Background" Value="Blue" />
                <Setter Property="local:OnMouseOver.Background" Value="Aqua" />
            </Style.Setters>
        </Style>
    </Window.Resources>
    <UniformGrid Columns="3">
        <Button Style="{StaticResource buttonBaseStyle}" />
        <Button Style="{StaticResource buttonRedStyle}" />
        <Button Style="{StaticResource buttonBlueStyle}" />
    </UniformGrid>
</Window>
  • 0
    Спасибо Рауль Нуньо, ваш ответ мне очень помог. это делает концепцию Присоединенной собственности для меня. Благодарю. : D

Ещё вопросы

Сообщество Overcoder
Наверх
Меню