Анимация в стилях WPF

336
30 октября 2017, 20:55

Столкнулся с проблемой при написании стиля, хочу что-бы при наведении на любой из прямоугольников двигалась картинка (block1) + изменялась прозрачность, если применяю в коде прямоугольника - все работает отлично, а в стиле выдает ошибку:

Свойство TargetName не может быть задано для типа Style Setter.

<Window.Resources>
    <Style TargetType="Rectangle">
        <Style.Triggers>
            <EventTrigger RoutedEvent="MouseEnter">
                <BeginStoryboard>
                    <Storyboard TargetName="block1" TargetProperty="Margin" >
                        <ThicknessAnimation From="-750,0,750,0" To="-200,0,200,0" Duration="0:0:0.7" DecelerationRatio="0.6"/>
                    </Storyboard>
                </BeginStoryboard>
                <BeginStoryboard>
                    <Storyboard TargetName="block1" TargetProperty="Opacity" >
                        <DoubleAnimation To="0.8" Duration="0:0:0.4"/>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
            <EventTrigger RoutedEvent="MouseLeave">
                <BeginStoryboard>
                    <Storyboard TargetName="block1" TargetProperty="Opacity" >
                        <DoubleAnimation To="0" Duration="0:0:0.1"/>
                    </Storyboard>
                </BeginStoryboard>
                <BeginStoryboard>
                    <Storyboard TargetName="block1" TargetProperty="Margin" >
                        <ThicknessAnimation To="-450,0,450,0" Duration="0:0:0.7"/>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </Style.Triggers>
    </Style>
</Window.Resources>
Answer 1

Проще всего, наверное, сделать общий стиль у картинки block1, которую вы собираетесь двигать. Вместо стиля у каждого прямоугольника мы соберём нужные свойства вместе. Обычно такое делается через MultiTrigger, но он реализует логику конъюнкции (то есть, триггер срабатывает, когда все условия выполнены), а нам нужна дизъюнкция (если хотя бы одно).

Поэтому нам придётся написать маленький конвертер.

class DisjunctionConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object p, CultureInfo ci) =>
        values.Any(v => (bool)v);
    public object[] ConvertBack(object value, Type[] targetTypes, object p, CultureInfo ci)=>
        throw new NotImplementedException();
}

Имея такой конвертер, всё получается довольно просто.

Вот пример XAML'а:

<Window.Resources>
    <local:DisjunctionConverter x:Key="OrConv"/>
</Window.Resources>
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <StackPanel>
        <Rectangle Fill="Red" Name="RedRect" Height="30" Margin="10,10,10,0" />
        <Rectangle Fill="Yellow" Name="YellowRect" Height="30"  Margin="10,10,10,0" />
        <Rectangle Fill="Green" Name="GreenRect" Height="30"  Margin="10,10,10,0" />
    </StackPanel>
    <Image Source="https://i.imgur.com/szJy4AT.jpg" Grid.Column="1" Margin="10">
        <Image.Style>
            <Style TargetType="Image">
                <Setter Property="Opacity" Value="0"/>
                <Style.Triggers>
                    <DataTrigger Value="True">
                        <DataTrigger.Binding>
                            <MultiBinding Converter="{StaticResource OrConv}">
                                <Binding ElementName="RedRect" Path="IsMouseOver"/>
                                <Binding ElementName="YellowRect" Path="IsMouseOver"/>
                                <Binding ElementName="GreenRect" Path="IsMouseOver"/>
                            </MultiBinding>
                        </DataTrigger.Binding>
                        <DataTrigger.EnterActions>
                            <BeginStoryboard>
                                <Storyboard TargetProperty="Opacity" >
                                    <DoubleAnimation To="0.8" Duration="0:0:0.4"/>
                                </Storyboard>
                            </BeginStoryboard>
                        </DataTrigger.EnterActions>
                        <DataTrigger.ExitActions>
                            <BeginStoryboard>
                                <Storyboard TargetProperty="Opacity" >
                                    <DoubleAnimation Duration="0:0:0.4"/>
                                </Storyboard>
                            </BeginStoryboard>
                        </DataTrigger.ExitActions>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Image.Style>
    </Image>
</Grid>

Результат:

READ ALSO
Проблема с microsoft azure AD

Проблема с microsoft azure AD

Здравствуйте, начну с того что я новичок в работе с ms azure, но у меня на работе появилась следующая задача, при помощи azure AD получить список пользователей...

282
Зависает форма c# при чтении com порта

Зависает форма c# при чтении com порта

ЗдравствуйтеЯ здесь новенький, поэтому сразу простите, если что-то оформлю не так

360
Определение Panel в виде отдельного класса

Определение Panel в виде отдельного класса

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

271
C# - Зацикливание выполнения части кода

C# - Зацикливание выполнения части кода

Как зациклить выполнение данного кода C#?

366