Замена фона кнопки в WPF на Aero

Итак, желание простое - изменить фон кнопки на светло-зеленый, зеленый при наведении курсора мыши на него и темно-зеленый при нажатии. Следующий XAML - моя первая попытка:

<Window x:Class="ButtonMouseOver.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
  <Grid>
    <Button Background="LightGreen">
      Hello
      <Button.Style>
        <Style TargetType="Button">
          <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="true">
              <Setter Property = "Background" Value="Green"/>
            </Trigger>
            <Trigger Property="IsPressed" Value="true">
              <Setter Property = "Foreground" Value="DarkGreen"/>
            </Trigger>
          </Style.Triggers>
        </Style>
      </Button.Style>
    </Button>
  </Grid>
</Window>

Но, увы, это не работает. Мы только на 1/3 пути к цели. Да, кнопка становится светло-зеленой, но как только вы наводите на нее курсор или нажимаете, вы получаете стандартный Aero chrome для соответствующих состояний кнопок. Не желая сдаваться, я пытаюсь развратиться следующим образом:

...
    <Button xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
            Background="LightGreen">
      Hello
      <Button.Template>
        <ControlTemplate TargetType="{x:Type Button}">
          <Microsoft_Windows_Themes:ButtonChrome SnapsToDevicePixels="true" 
            x:Name="Chrome" Background="{TemplateBinding Background}" 
            BorderBrush="{TemplateBinding BorderBrush}" RenderDefaulted="{TemplateBinding IsDefaulted}" 
            RenderMouseOver="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding IsPressed}"
            >
            <ContentPresenter Margin="{TemplateBinding Padding}"
                                          VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                          HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                          RecognizesAccessKey="True"
                                          SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
          </Microsoft_Windows_Themes:ButtonChrome>
        </ControlTemplate>
      </Button.Template>
      <Button.Style>
        <Style TargetType="Button">
          <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="true">
              <Setter Property = "Background" Value="Green"/>
            </Trigger>
            <Trigger Property="IsPressed" Value="true">
              <Setter Property = "Foreground" Value="DarkGreen"/>
            </Trigger>
          </Style.Triggers>
        </Style>
      </Button.Style>
    </Button>
...

Теперь мы ' Мы получили весь чертов шаблон управления, взятый из Aero.NormalColor.xaml . Увы, это ничего не меняет. Затем я удаляю два атрибута ( RenderPressed и RenderMouseOver ) из элемента Microsoft_Windows_Themes: ButtonChrome . Тем не менее, изменений нет. Затем я удаляю настройку атрибута Button Background , оставляя только объявление пространства имен для сборки PresentationFramework.Aero:

...
<Button xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero">
  Hello
...

Наконец, у нас есть прогресс. Мы перешли от 1/3 требований к 2/3 пути, при этом IsMouseOver и IsPressed работают, но нет светло-зеленого фона во время нормального состояния кнопки (когда кнопка не наведена и не нажата), поскольку я удалил свойство Background из кнопки, чтобы два других состояния применялись и были видны. Теперь, после того, как этот маниакальный XAML не смог получить фон LightGreen для нормального состояния кнопки, я изменяю стиль, добавляя туда и цвет фона:

  <Button xmlns...
    <ControlTemplate...
    ...
    </ControlTemplate>
    <Button.Style> 
      <Style TargetType="Button">
        <!-- ##### Normal state button background added ##### -->
        <Setter Property="Background" Value="LightGreen" />
        <!-- ################################################ -->
        <Style.Triggers>
          <Trigger Property="IsMouseOver" Value="true">
            <Setter Property = "Background" Value="Green"/>
          </Trigger>
          <Trigger Property="IsPressed" Value="true">
            <Setter Property = "Background" Value="DarkGreen"/>
          </Trigger>
        </Style.Triggers>
      </Style>
    </Button.Style> 
  </Button>

Наконец, он работает, как задумано.

Я сумасшедший, Или это (и многое другое) обручи, которые вам нужно пройти с темой Aero, чтобы просто изменить цвет фона кнопки в некоторых из ее различных состояний (нормальный, наведенный, нажатый)? Возможно, жизнь была бы не так уж плоха, если бы мне не пришлось включать туда весь чертов ButtonTemplate только для того, чтобы удалить из него два атрибута ( RenderMouseOver и RenderPressed ).

Спасибо за любую помощь - я на грани остроумия.

Обновление: Но подождите, это еще не все. Вместо удаления атрибутов RenderMouseOver и RenderPressed из шаблона элемента управления, простое изменение их с:

<Microsoft_Windows_Themes:ButtonChrome SnapsToDevicePixels="true" ...
  RenderMouseOver="{TemplateBinding IsMouseOver}"  
  RenderPressed="{TemplateBinding IsPressed}" ...

на:

<Microsoft_Windows_Themes:ButtonChrome SnapsToDevicePixels="true" ...
  RenderMouseOver="{Binding IsMouseOver}"  
  RenderPressed="{Binding IsPressed}" ...

... также устраняет проблему (игнорирование триггеров стиля кнопки). Я думаю, что корень проблемы в том, что привязки шаблонов применяются во время компиляции (по соображениям производительности), а обычные привязки применяются во время выполнения. Из-за этого привязки из триггеров стиля от отдельных кнопок не используются, если атрибуты используют привязки шаблонов (т. Е. Вместо них используются IsMouseOver и IsPressed из исходного шаблона).

Сказав все вышесказанное, вот канонический пример изменения фона кнопки в Aero с сохранением исходного шаблона управления:

<Window x:Class="ButtonMouseOver.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
  <Grid>
    <Button>
      Hello
      <Button.Template>
        <ControlTemplate TargetType="{x:Type Button}">
          <Microsoft_Windows_Themes:ButtonChrome SnapsToDevicePixels="true" 
            x:Name="Chrome" Background="{TemplateBinding Background}" 
            BorderBrush="{TemplateBinding BorderBrush}" RenderDefaulted="{TemplateBinding IsDefaulted}" 
            RenderMouseOver="{Binding IsMouseOver}" RenderPressed="{Binding IsPressed}"
            >
            <ContentPresenter Margin="{TemplateBinding Padding}"
                                          VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                          HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                          RecognizesAccessKey="True"
                                          SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
          </Microsoft_Windows_Themes:ButtonChrome>
        </ControlTemplate>
      </Button.Template>
      <Button.Style>
        <Style TargetType="Button">
          <Setter Property="Background" Value="LightGreen"/>
          <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="true">
              <Setter Property = "Background" Value="Green"/>
            </Trigger>
            <Trigger Property="IsPressed" Value="true">
              <Setter Property = "Foreground" Value="DarkGreen"/>
            </Trigger>
          </Style.Triggers>
        </Style>
      </Button.Style>
    </Button>
  </Grid>
</Window>

Это, конечно, предполагает, что только одна кнопка имеет такой стиль, в противном случае шаблон и стиль можно переместить куда-нибудь в раздел ресурсов. Кроме того, нет триггера для состояния кнопки по умолчанию, но его легко добавить в приведенный выше пример (не забудьте изменить атрибут RenderDefaaled в шаблоне элемента управления, чтобы использовать Binding вместо TemplateBinding).

Если кто-нибудь есть какие-либо предложения о том, как переопределить TemplateBinding с Binding только для двух атрибутов в шаблоне управления, которые необходимо изменить, без повторения всего определения chrome из оптовой продажи aero xaml, я все слышу.

9
задан Michael Goldshteyn 13 December 2010 в 21:06
поделиться