Faced a problem when writing a style, I want something to move on to any of the rectangles; the picture (block1) + would change transparency ; if I use a rectangle in the code, everything works fine, and in the style it gives an error:

The TargetName property cannot be set for the Style Setter type.

<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> 
  • Well, all right, where does the style know that you have block1? - VladD
  • Those. If I insert this code into 20 rectangles, then this will not affect the optimization of the application? - Jefoce
  • I don’t quite understand what kind of optimization we are talking about, if you just don’t compile yet :-P - VladD
  • The fact is that now this code without a style is installed in my <> each rectangle, there are 15 of them in total. And I wanted to optimize it through the style, but it seems here only through the logic c # you can - Jefoce

1 answer 1

The easiest way is probably to make the overall style of the block1 picture you are going to move. Instead of the style of each rectangle, we will collect the necessary properties together. This is usually done through MultiTrigger , but it implements the logic of the conjunction (that is, the trigger is triggered when all conditions are met), and we need a disjunction (if at least one).

Therefore, we have to write a small converter.

 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(); } 

Having such a converter, everything is pretty simple.

Here is an example of a 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> 

Result:

it is not only valuable fur

  • Thank you very much! : D It remains to understand the work of the converter) - Jefoce
  • @Jefoce: well, the Any function returns true when at least one of the array values ​​passed through the lambda v => (bool)v is true . As bool arrives at the entrance, packed into an object, the lambda simply pulls that same bool back. Total: true if at least one value from the array contains true . - VladD