2010-12-12 4 views
9

Итак, желание прост, измените фон кнопки на LightGreen, зеленый, когда курсор мыши на него навирается и DarkGreen при нажатии. Следующей XAML является моя первая попытка:Переопределение фона кнопки в WPF на 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 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. Тем не менее, изменений нет. Затем я удаляю установку атрибута Баттона 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, чтобы удалить из него два атрибута (10 и RenderPressed).

Благодарим за помощь - я нахожусь в конце wit.

Обновление: Но подождите, есть еще кое-что. Вместо удаления 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> 

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

Если у кого есть какие-либо предложения о том, как переопределении TemplateBinding Связующее только для двух атрибутов в шаблоне элемента управления, которые необходимо изменить, не повторяя все определение хрома от аэро XAML оптом, я все уши.

ответ

2

В шаблоне по умолчанию для Button используется ButtonChrome, который выполняет собственный чертеж. Если вы хотите полностью избавиться от внешнего вида, вам необходимо определить свой собственный шаблон без ButtonChrome. Я знаю, это звучит утомительно, но вам нужно сделать это только один раз: вы можете поместить свой собственный стиль в словарь ресурсов и просто ссылаться на него с помощью StaticResource. Обратите внимание, что вы также можете применить стиль ко всем кнопкам в вашем приложении, используя {x:Type Button} в качестве ключа стиля (x:Key)

+0

Проблема в том, что я просто хочу изменить фон кнопки. Aero chrome обрабатывает это правильно, используя атрибут Background Button для нормального состояния кнопки. Но эта обработка ошибочна, потому что фон меняется прямо на мышь и когда кнопка нажата. Нет простого способа, по-видимому, изменить фон кнопки в этих двух состояниях. Это побеждает целую цель иметь атрибут фона в Button (и, возможно, другие визуальные алементы). –

+0

Свойство Background является общим для всех элементов управления, поэтому оно все равно будет, но ничто не гарантирует, что шаблон учтет его. Я могу воспроизвести вашу проблему с темой Aero и похожей проблемой с темой Luna. Кажется, ButtonChrome не учитывает фон для определенных состояний ... Во всяком случае, я не думаю, что стандартная кнопка chrome предназначена для настройки цветов. Если вы хотите сделать это, просто не используйте хром ... Очень легко создать собственный шаблон кнопки без него. –

+0

Из свойства MSDN (свойство Control.Background): свойство Background применяется только к состоянию покоя элемента управления. Стиль по умолчанию элемента управления определяет его внешний вид при изменении состояния элемента управления. Например, если вы задаете свойство Background на кнопке, кнопка имеет это значение только в том случае, если оно не нажато или не отключено. Если вы хотите создать элемент управления, который имеет более продвинутую настройку фона, вы должны определить стиль элемента управления. –

Смежные вопросы