Есть ли способ использовать установщик стиля для свойств свойств? - PullRequest
5 голосов
/ 02 января 2011

Редактировать: В исходном вопросе я сделал несколько неправильных предположений о том, как работают сеттеры, поэтому я изменил его, чтобы, надеюсь, быть более точным и полезным.

Я попытался сделать некоторые пункты меню более интересными, чтобы значки казались полупрозрачными, если мышь не находится над элементом. Если мышь входит, значок должен быть анимирован, чтобы стать полностью видимым. Анимация работает, Storyboard.TargetProperty обеспечивает прямой доступ к свойству непрозрачности иконки:

<Style x:Key="MenuItemMouseOverStyle" TargetType="MenuItem">
    <Style.Triggers>
        <EventTrigger RoutedEvent="MouseEnter">
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Icon.Opacity">
                        <EasingDoubleKeyFrame KeyTime="0" Value="0.5"/>
                        <EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="1"/>
                    </DoubleAnimationUsingKeyFrames>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
        <EventTrigger RoutedEvent="MouseLeave">
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Icon.Opacity">
                        <EasingDoubleKeyFrame KeyTime="0" Value="1"/>
                        <EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="0.5"/>
                    </DoubleAnimationUsingKeyFrames>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Style.Triggers>
</Style>

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

<Setter Property="Icon.Opacity" Value="0.5"/>

Edit: Сеттеры не работают так, как я пытался их использовать, вы не можете получить доступ к свойствам свойств (см. Ответы) Единственное, что вы можете сделать, это указать целевой класс, если целевой тип стиля не был установлен, следующие стили должны быть эквивалентны:

<Style x:Key="Style1" TargetType="Image">
    <Setter Property="Opacity" Value="0.5"/>
</Style>
<Style x:Key="Style2">
    <Setter Property="Image.Opacity" Value="0.5"/>
</Style>

Так что мой вопрос, есть ли способ заставить это работать как-то с помощью сеттера.

(Мой текущий обходной путь - раскадровка с одним ключевым кадром, которая запускается с событием Loaded, которое работает довольно хорошо)

Ответы [ 2 ]

1 голос
/ 03 января 2011

Итак, после прочтения ответа Милика и выяснения, что вы можете иметь стиль в стиле через ресурсы, вам, вероятно, ближе всего будет сделать это с помощью сеттера, - это встроенный стиль для доступа к непрозрачности значка. Здесь я предполагаю, что значок является изображением, поэтому я использую его в качестве целевого типа, поэтому полный стиль выглядит следующим образом:

<Style x:Key="MenuItemMouseOverStyle" TargetType="MenuItem">
    <Style.Resources>
        <Style TargetType="Image">
            <Setter Property="Opacity" Value="0.5"/>
        </Style>
    </Style.Resources>
    <Style.Triggers>
        <EventTrigger RoutedEvent="MouseEnter">
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Icon.Opacity">
                        <EasingDoubleKeyFrame KeyTime="0" Value="0.5"/>
                        <EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="1"/>
                    </DoubleAnimationUsingKeyFrames>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
        <EventTrigger RoutedEvent="MouseLeave">
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Icon.Opacity">
                        <EasingDoubleKeyFrame KeyTime="0" Value="1"/>
                        <EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="0.5"/>
                    </DoubleAnimationUsingKeyFrames>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Style.Triggers>
</Style>

Единственная проблема с этим состоит в том, что он фактически не устанавливает Icon.Opacity, но непрозрачность всех изображений, которые могут возникнуть в MenuItem.

1 голос
/ 02 января 2011

Я не думаю, что вы можете получить доступ к такому свойству, так что само приведение не является проблемой. Даже если бы Icon был Type Image, он все равно не работал бы. Вы можете попробовать с непрозрачностью фона для сетки, например. Фон является свойством зависимости для сетки, а непрозрачность - свойством зависимости для кисти, но следующая строка не будет работать

<Grid Background.Opacity="0.8"/>

Вы получите сообщение об ошибке

Присоединяемое свойство «Непрозрачность» было не найден в типе «Фон».

Вы должны установить это в самом фоне, как это

<Grid>
    <Grid.Background>
        <SolidColorBrush Opacity="0.8"/>
    </Grid.Background>
</Grid>

Так что это значит, когда вы делаете что-то подобное

<Grid TextBlock.Foreground="Red">
    <TextBlock Text="Test"/>
</Grid>

вы на самом деле используете передний план присоединенного свойства для TextBlock.

Изображение не имеет вложенного свойства, называемого непрозрачностью, поэтому вы также не можете сделать это

<MenuItem Image.Opacity="0.8" />

Другой обходной путь, кроме того, который вы уже делаете, - это использовать что-то вроде этого (самый верхний элемент MenuItem или везде, где вы хотите его использовать).

<MenuItem x:Name="topMenuItem"
          ...>
    <MenuItem.Resources>
        <Style TargetType="Image">
            <Setter Property="Opacity" Value="0.5"/>
        </Style>
    </MenuItem.Resources>
    <!-- ... -->
</MenuItem>
...