2013-05-04 4 views
1

У меня есть Button с настраиваемым внешним видом, определяемым ControlTemplate.Поведение кнопки WPF с использованием триггеров

Он содержит Canvas, который содержит Path. Я хотел бы добавить изменения в Path.Opacity в зависимости от состояния мыши:

  • по умолчанию - 0,5
  • мыши над, не нажата - 1,0
  • мыши на штампованные - 0,5

Первые случаи покрываются просто установкой местного значения Path.Opacity на 0.5 и добавлением одного Trigger для IsMouseOver:

<Button x:Class="ImagingShop.Panosphere.Controls.PathButton" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      mc:Ignorable="d" 
      d:DesignHeight="100" d:DesignWidth="100" 
     Name="pathButton"> 

    <Button.Template> 
     <ControlTemplate> 
      <Canvas Background="Transparent" Width="{TemplateBinding Width}" Height="{TemplateBinding Width}"> 
       <Canvas.Style> 
        <Style TargetType="Canvas"> 
         <Setter Property="Path.Opacity" Value="0.5"/> 
         <Style.Triggers> 
          <Trigger Property="IsMouseOver" Value="True"> 
           <Setter Property="Path.Opacity" Value="1.0"/> 
          </Trigger> 
         </Style.Triggers> 
        </Style> 
       </Canvas.Style> 
       <Path Data="{Binding ElementName=pathButton, Path=PathData}" Stretch="Uniform" Fill="#FFFFFFFF" Width="{TemplateBinding Width}" Height="{TemplateBinding Width}"/> 
      </Canvas> 
     </ControlTemplate> 
    </Button.Template> 

    <Grid> 

    </Grid> 
</Button> 

Однако третий случай не работает. Я добавил следующий триггер:

<MultiTrigger> 
    <MultiTrigger.Conditions> 
     <Condition Property="IsMouseOver" Value="True"/> 
     <Condition Property="Button.IsPressed" Value="True"/> 
    </MultiTrigger.Conditions> 
    <Setter Property="Path.Opacity" Value="0.75"/> 
</MultiTrigger> 

Так это должно установить Path.Opacity к 0.75 является наведение указателя мыши на кнопку И нажатия кнопки.

Я застрял в этом, так как непрозрачность изменена на 0.5 вместо 0.75! Триггер, кажется, относится, но не работает, как ожидалось ...

+0

Итак - кнопка restyle не может использоваться только с помощью XAML? Кажется, что Button.IsPressed должен работать - есть [пример XAML] (http://msdn.microsoft.com/en-us/library/system.windows.controls.primitives.buttonbase.ispressed.aspx), выполняющий именно это , – Libor

ответ

1

Почему вы просто не используете Opacity в Button и имеют синхронизируется по Button «s Style непосредственно, Ваш ControlTemplate не имеет ничего, кроме этого Path в любом случае.

<Style TargetType="{x:Type local:PathButton}"> 
    <Setter Property="Opacity" 
      Value=".5" /> 
    <Setter Property="OverridesDefaultStyle" 
      Value="True" /> 
    <Setter Property="Template"> 
    <Setter.Value> 
     <ControlTemplate TargetType="{x:Type local:PathButton}"> 
     <Canvas Width="{TemplateBinding Width}" 
       Height="{TemplateBinding Width}" 
       Background="Transparent"> 
      <Path Width="{TemplateBinding Width}" 
       Height="{TemplateBinding Width}" 
       Data="{Binding ElementName=pathButton, 
           Path=PathData}" 
       Fill="#FFFFFFFF" 
       Opacity="{TemplateBinding Opacity}" 
       Stretch="Uniform" /> 
     </Canvas> 
     </ControlTemplate> 
    </Setter.Value> 
    </Setter> 
    <Style.Triggers> 
    <Trigger Property="IsMouseOver" 
       Value="True"> 
     <Setter Property="Opacity" 
       Value="1" /> 
    </Trigger> 
    <Trigger Property="IsPressed" 
       Value="True"> 
     <Setter Property="Opacity" 
       Value=".75" /> 
    </Trigger> 
    </Style.Triggers> 
</Style> 

будет производить выходные ваши ожидания.

Update:

Вы можете просто иметь Style в ResourceDictionary и имеют декларацию Подкласс в файл с фоновым кодом. Это создаст только один файл xaml. В этом методе не осталось 2 xaml-файлов.

Также перешли на переплет для PathData на привязку RelativeSource.

Вы можете скачать образец этого файла с Here. Откройте его и проверьте его.

Я также использовал надстройку NestIn, которая позволяет группировать файлы в пользовательские группы, редактируя файл vsproj и добавляя атрибут DependsOn. Это позволяет группировать файлы ResourceDictionary и Code-behind Class в один Entity PathButton.xaml так же, как UserControl и Window смотрите в IDE с их файлом кода.

+0

ОК, это частично работает, но мне пришлось перемещать весь стиль за пределами PathButton.xaml code - причины, по которым я хотел иметь его внутри, это то, что '{TemplateBinding PathData}' не работает, только '{Binding ElementName = pathButton, Path = PathData}'. PathData - это нормальное свойство зависимости типа String. Стиль теперь относится к некоторому имени элемента, который является магической константой, и я хотел бы, чтобы код был как можно более автономным (единственный файл XAML был бы лучшим ...). Если каждый пользовательский элемент управления имеет по крайней мере два файла XAML (один для кода и один для стиля), код будет довольно разбросан ... – Libor

+0

@Libor Я обновил свой ответ с небольшим описанием и ссылкой на загрузку Dropbox, которую вы может получить и посмотреть, как вы можете структурировать это только в 1 файле xaml, а также используя привязку RelativeSource вместо TemplateBinding для PathData. Скачайте его и посмотрите сами. – Viv

+0

Спасибо! Теперь это работает как шарм. Сначала я попытался добавить стиль PathButton внутри Button.Style, но это вызвало несоответствие типов, поскольку стиль нацелен на PathButton, а не на Button. Благодаря вашему коду я понял, что мне не нужно XAML для кнопки, кроме самого стиля. Я все еще запутался в TemplateBindingExtension, так как он работает с свойствами управления WPF плавно, но не работает вообще с пользовательскими свойствами управления ... Ну, по крайней мере, есть решение (хотя оно выглядит не так просто и элегантно, как TemplateBinding). – Libor

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