Как заставить Style.Triggers запускать стиль с другим именем для применения

Допустим, у меня есть следующее:

<Style TargetType="{x:Type TextBox}">
    <Setter Property="BorderThickness" Value="1" />
    <Setter Property="BorderBrush" Value="Gray" />
    <Style.Triggers>
        <Trigger Property="IsFocused" Value="true"> 
            <Setter Property="BorderBrush" Value="Green" />
            <Setter Property="BorderThickness" Value="2" />
        </Trigger>
    </Style.Triggers> 
</Style>

Это прекрасно работает, и здесь нет ничего особенно плохого, но это довольно простой случай. Что произойдет, если я хочу, чтобы состояние стиля IsFocused было указано как явный стиль, как ссылаться на этот стиль как на стиль IsFocused, т.е.

<Style x:key="ActiveStyle" TargetType="{x:Type TextBox}">
    <Setter Property="BorderBrush" Value="Green" />
    <Setter Property="BorderThickness" Value="2" />
</Style>

<Style TargetType="{x:Type TextBox}">
    <Setter Property="BorderThickness" Value="1" />
    <Setter Property="BorderBrush" Value="Gray" />
    <Style.Triggers>
        <Trigger Property="IsFocused" Value="true">
           -- Here I want to reference ActiveStyle and not copy the copy the setters
        </Trigger>
    </Style.Triggers> 
</Style>

person vdhant    schedule 26.07.2009    source источник


Ответы (4)


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

<Style x:Key="ActiveStyle" TargetType="{x:Type TextBox}">
    <Style.Triggers>
        <Trigger Property="IsFocused" Value="true">
            <Setter Property="BorderBrush" Value="Green" />
            <Setter Property="BorderThickness" Value="2" />
        </Trigger>
    </Style.Triggers>
</Style>

<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource ActiveStyle}">
    <Setter Property="BorderThickness" Value="1" />
    <Setter Property="BorderBrush" Value="Gray" />
</Style>

другого выхода не вижу :(

person Nicolas Dorier    schedule 26.07.2009

Есть еще третий способ сделать это.

Создайте два именованных шаблона элемента управления для вашего элемента управления:

<ControlTemplate x:Key="NotFocused" TargetType="{x:Type TextBox}">  
    . . .
</ControlTemplate>  

<ControlTemplate x:Key="Focused" TargetType="{x:Type TextBox}">   
    . . .
</ControlTemplate>

Затем вы создаете стиль по умолчанию для TextBox с триггерами в нем:

<Style TargetType="{x:Type TextBox}">   
    <Style.Triggers>
        <Trigger Property="IsFocused" Value="True">
            <Setter Property="Template" Value="{StaticResource Focused}" />
        </Trigger>
        <Trigger Property="IsFocused" Value="False">
            <Setter Property="Template" Value="{StaticResource NotFocused}" />
        </Trigger>
    </Style.Triggers>
</Style>

Тони

person Tony Vitabile    schedule 19.03.2012
comment
Это вызывает у меня исключение: «Объект стиля не может влиять на свойство стиля объекта, к которому он применяется». Это вроде как очевидно, как стиль может измениться на какой-то другой стиль, но при этом продолжать работать? - person svick; 23.11.2012
comment
Я мог бы поклясться, что у меня был пример этого в моем приложении, но я не могу найти его сейчас. Я не припомню такой ошибки в моем развитии, которая, по сути, ничего не значит. Мне придется поиграть с этим когда-нибудь, когда у меня будет несколько свободных минут. - person Tony Vitabile; 26.11.2012
comment
@svick: я отредактировал свой пример, так что теперь он использует работающий код. Сейчас это может быть не совсем актуально для исходного вопроса, поскольку он использует шаблоны элементов управления и стиль по умолчанию. Но это работает. - person Tony Vitabile; 06.12.2012

WPF предоставляет специальное свойство для этого FrameworkElement.FocusVisualStyle. Итак, назначьте его :)

<TextBox FocusVisualStyle="{StaticResource ActiveStyle}" .....

Или другой способ с помощью сеттеров

<Style TargetType="{x:Type TextBox}">
 <Setter Property="BorderThickness" Value="1" />
 <Setter Property="BorderBrush" Value="Gray" />    
 <Setter Property="FocusVisualStyle" >
  <Setter.Value>
    <Style x:key="ActiveStyle" TargetType="{x:Type TextBox}">
       <Setter Property="BorderBrush" Value="Green" />
       <Setter Property="BorderThickness" Value="2" />
    </Style>
   </Setter.Value>
  </Setter>
 </Style>
person Jobi Joy    schedule 26.07.2009

Моя ситуация связана с необходимостью отображать изображение значка блокировки/разблокировки в поле просмотра кнопки. К сожалению, в окне просмотра нет прямого свойства Content. Основываясь на приведенном выше ответе @Tony, вот рабочий пример, который включает его ответ для моей ситуации.

<Button Padding="5 0" Margin="0" Cursor="Hand" Style="{StaticResource IconButton}">
    <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center" >
        <Viewbox Stretch="Fill" Height="20" Width="20">
            <ContentControl >
                <ContentControl.Resources>
                    <ControlTemplate x:Key="Open" TargetType="ContentControl">
                        <ContentControl Style="{StaticResource LockOpenIcon}" />
                    </ControlTemplate>
                    <ControlTemplate x:Key="Closed" TargetType="ContentControl">
                        <ContentControl Style="{StaticResource LockClosedIcon}" />
                    </ControlTemplate>
                </ContentControl.Resources>
                <ContentControl.Style>
                    <Style TargetType="{x:Type ContentControl}" >
                        <Setter Property="Template" Value="{StaticResource Open}" />
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding Path=WorkflowAccessibility, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" Value="{x:Static da:GatewayWorkflowAccessibility.VisibleDisabled}">
                                <Setter Property="Template" Value="{StaticResource Closed}" />
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </ContentControl.Style>
            </ContentControl>
        </Viewbox>
    </StackPanel>
</Button>
person Galactic    schedule 18.08.2020