How to make Rotate in WPF - wpf

I beginner in wpf and I want rotate a TextBlock but I have error:"Cannot resolve all property references in the property path 'RotateTransform.Angle'. Verify that applicable objects support the properties."
<TextBlock Grid.Row="1" Grid.Column="1" RenderTransformOrigin="0.5,0.5" Style="{StaticResource Rotate}">
<TextBlock.RenderTransform>
<TransformGroup>
<RotateTransform Angle="-16.308"/>
</TransformGroup>
</TextBlock.RenderTransform>
<TextBlock.Background>
<ImageBrush ImageSource="image/1.png"></ImageBrush>
</TextBlock.Background>
</TextBlock>
and this is my style
<Style x:Key="Rotate" TargetType="{x:Type TextBlock}">
<!--<Setter Property="Width" Value="10"></Setter>
<Setter Property="Height" Value="10"></Setter>-->
<Setter Property="Background" Value="Black"></Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Trigger.EnterActions >
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="RotateTransform.Angle" To="-360" Duration="0:0:1" RepeatBehavior="Forever"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>

You should be able to use the orientation of a stack panel in your xaml to rotate easily, but this does not give immediate access to the angle.
<StackPanel Orientation="Horizontal">
<Textbox ...../>
</StackPanel>
Or in your style you can add a setter property.
<Setter Property="RenderTransform">
<Setter.Value>
<RotateTransform Angle="-90"></RotateTransform>
</Setter.Value>
</Setter>

If you need TransformGroup in your RenderTransorm, then StoryboardTargetProperty will be look like
RenderTransform.Children[0].Angle
If you leave only RotateTransform there, then it will be
RenderTransform.Angle
In both cases, as you see, we start searching property from RenderTransform.

Related

Button with both background image and color WPF

I have a button in my wpf app, looking like :
<Button x:Name="button" Content="" HorizontalAlignment="Left" Margin="402,10,0,0" VerticalAlignment="Top" Width="26" Height="28" BorderBrush="{x:Null}" Grid.Column="1" Foreground="White">
<Button.Background>
<ImageBrush ImageSource="cls_blk_btn.png" Stretch="None"/>
</Button.Background>
</Button>
Now as you can see the button has a background image, is it possible to have a background color keeping the image also ??
What i am trying to do is change the button's background color(keeping the image as it is) on mouse enter with this :
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<EventTrigger RoutedEvent="Button.MouseEnter">
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="Color" To="#FF484A4D" Duration="0:0:0.1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Button.MouseLeave">
<BeginStoryboard>
<Storyboard>
<ParallelTimeline >
<ColorAnimation Storyboard.TargetProperty="Color" To="#FF57626C" Duration="0:0:0.1" />
</ParallelTimeline>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
</Button.Style>
The problem is, as the background is an image, i get exceptions while trying to change the color...Any help in keeping the image as it is and changing the backColor ???
THIS IS WHAT I JUST TRIED
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Background">
<Setter.Value>
<ImageBrush ImageSource="resources\c_ml.bmp" Stretch="Fill"/>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background">
<Setter.Value>
<ImageBrush ImageSource="Resources\c_mo.bmp" Stretch="Fill"/>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
But it gives me 'Provide value on 'System.Windows.Baml2006.TypeConverterMarkupExtension' threw an exception.' in line 45.The lines throwing the exceptions are:
<Style TargetType="{x:Type Button}">
<Setter Property="Background">
<Setter.Value>
<ImageBrush ImageSource="resources\c_ml.png" Stretch="Fill"/>
</Setter.Value>
</Setter>
<Style.Triggers>
Any idea how to fix it ?
I FIXED MY SECOND ERROR BUT HAVE A NEW PROBLEM
The second error occured because i didn't include the pictures in my project.After including, i have a new problem. Now , on mouse over, The button becomes white, i mean it changes it's Background color instead of changing the image...What's wrong ?
Do you have to put the Image in background? If you just want to show an Image with background in the button, it will be lot easier to put the Image in Button.Content and animate the background, e.g.:
<Button x:Name="button" HorizontalAlignment="Left" Margin="402,10,0,0" VerticalAlignment="Top" Width="260" Height="280" BorderBrush="{x:Null}" Foreground="White">
<Button.Content>
<Image Source="image.png" Stretch="None" />
</Button.Content>
<Button.Background>
<SolidColorBrush Color="#FF57626C" />
</Button.Background>
<Button.Style>
<Style TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}" >
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<EventTrigger RoutedEvent="Button.MouseEnter">
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="Background.Color" To="#FF484A4D" Duration="0:0:0.1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Button.MouseLeave">
<BeginStoryboard>
<Storyboard>
<ParallelTimeline >
<ColorAnimation Storyboard.TargetProperty="Background.Color" To="#FF57626C" Duration="0:0:0.1" />
</ParallelTimeline>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
FIXED IT MYSELF
<Button.Content>
<StackPanel>
<Image Name="image1" Source="pack://application:,,,/OffPo Diagnostic Tool;component/resources/c_ml.bmp" Stretch="Fill" >
<Image.Style>
<Style TargetType="Image">
<Setter Property="Visibility" Value="Visible" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsMouseOver, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}}" Value="True">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
<Image Name="image2" Source="pack://application:,,,/OffPo Diagnostic Tool;component/resources/c_mo.bmp" Stretch="Fill" >
<Image.Style>
<Style TargetType="Image">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsMouseOver, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}}" Value="True">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</StackPanel>
</Button.Content>

Expander header text alignment

So I changed the orientation of the expander to align vertically rather than horizontally but in the closed state the expander header text is aligning horizontally. Please tell me there is a way to easily fix this without expression blend etc.
<Expander Header="My Header">
I was hoping for something like AlignHeaderText vertically but I see no options for it? Does anyone have a different way they could "show" me?
So taking from the mentoring H.B provided I came up with this:
<StackPanel Orientation="Horizontal" Margin="0,0,342,0" Width="318">
<StackPanel.Triggers>
<EventTrigger RoutedEvent="Expander.Expanded" SourceName="expander1">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation From="0" To="1.2" Duration="0:0:0.45" Storyboard.TargetName="content" Storyboard.TargetProperty="(FrameworkElement.LayoutTransform).(ScaleTransform.ScaleX)"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</StackPanel.Triggers>
<Expander ExpandDirection="Right" Name="expander1" OpacityMask="#6C806969" Background="#FF807171">
<Expander.LayoutTransform>
<RotateTransform Angle="90"></RotateTransform>
</Expander.LayoutTransform>
<Expander.Header>
<TextBlock
Text="HEADER"
Width="{Binding
RelativeSource={RelativeSource
Mode=FindAncestor,
AncestorType={x:Type Expander}},
Path=ActualWidth}"
/>
</Expander.Header>
<Grid x:Name="content" Background="#FF807171" Width="178">
<Grid.LayoutTransform>
<ScaleTransform ScaleX="0" ScaleY="1"/>
</Grid.LayoutTransform>
</Grid>
</Expander>
Unfortunately it does this to the expander:
It places the text at the top and the button in the middle, I was hoping for the button at the top and the text after the button?
If I change Path=ActualWidth to Height the button moves up but the header text is still left of the button and not below it?
My solution (without another properties) - based on H.B. and Sheikh Neyamat answers:
<Expander ExpandDirection="Right">
<Expander.Header>
<TextBlock Text="Header">
<TextBlock.LayoutTransform>
<RotateTransform Angle="90"/>
</TextBlock.LayoutTransform>
</TextBlock>
</Expander.Header>
// Content - listbox in my case
</Expander>
Assign a TextBlock as Header via element syntax and apply a RotateTransform as the TextBlock's LayoutTransform to get the rotation. If you want vertical text that can be done differently.
An example here supporting above suggestions.
You need to also set the ExpandDirection property and set the rotation in a header template.
Below a style that flip direction when folded
<StackPanel Orientation="Horizontal">
<StackPanel.Resources>
<Style TargetType="Expander">
<Style.Triggers>
<Trigger Property="IsExpanded" Value="False">
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{Binding}">
<TextBlock.LayoutTransform>
<RotateTransform Angle="90"/>
</TextBlock.LayoutTransform>
</TextBlock>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="ExpandDirection" Value="Right"/>
</Trigger>
</Style.Triggers>
<Setter Property="BorderBrush" Value="DarkGray"/>
<Setter Property="Margin" Value="1,0,1,1"/>
<Setter Property="Padding" Value="2"/>
<Setter Property="VerticalContentAlignment" Value="Top"/>
</Style>
</StackPanel.Resources>
<Expander Header="Command Data">
<!-- some content -->
</Expander>
<Expander Header="Line Status">
<!-- some content -->
</Expander>
</StackPanel>

Use style trigger to set property of a nested object

I have a small polygon written on the large canvas. I want to highlight a polygon when mouse is moving over the canvas. The code is like this:
<UserControl ...>
<Canvas Name="canvas" Height="22" Width="22">
<Canvas.Resources>
<Style TargetType="Canvas">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="false">
<Setter Property="polygon.Stroke" Value="#EEEEEE"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="polygon.Stroke" Value="Aqua"/>
</Trigger>
</Style.Triggers>
</Style>
</Canvas.Resources>
<Polygon Points="11,1 16,6 16,16 11,21" Name="polygon">
<Polygon.Fill>
<SolidColorBrush Color="#EEEEEE"/>
</Polygon.Fill>
</Polygon>
</Canvas>
</UserControl>
However setter does not see the "polygon".
You cannot use Setters like that, if you use this kind of notation the engine will look for an attached property, or if no Style.TargetType was set for a property on the type before the dot.
The easiest thing to do is probably applying a style to the polygon itself and using a DataTrigger which binds to the Canvas so you can trigger on its properties.
<Polygon Points="11,1 16,6 16,16 11,21" Name="polygon">
<Polygon.Fill>
<SolidColorBrush Color="#EEEEEE"/>
</Polygon.Fill>
<Polygon.Style>
<Style TargetType="{x:Type Polygon}">
<Style.Triggers>
<DataTrigger
Binding="{Binding Path=IsMouseOver,
RelativeSource={RelativeSource
AncestorType={x:Type Canvas}}}"
Value="True">
<Setter Property="Stroke" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
<Polygon.Style>
</Polygon>
Try EventTrigger, because other kinds of triggers you could only use in templates or styles. And we already know that Style.Trigger doesn't allow your scenario. So here is working example for you:
<Canvas Name="canvas" Height="22" Width="22">
<Polygon Points="11,1 16,6 16,16 11,21" Name="polygon">
<Polygon.Fill>
<SolidColorBrush x:Name="brush" Color="#EEEEEE"/>
</Polygon.Fill>
<Polygon.Triggers>
<EventTrigger RoutedEvent="UIElement.MouseEnter">
<BeginStoryboard>
<Storyboard Storyboard.TargetName="brush" Storyboard.TargetProperty="Color">
<ColorAnimation From="#EEEEEE" To="Aqua" Duration="00:00:00.01" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="UIElement.MouseLeave">
<BeginStoryboard>
<Storyboard Storyboard.TargetName="brush" Storyboard.TargetProperty="Color">
<ColorAnimation From="Aqua" To="#EEEEEE" Duration="00:00:00.01" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Polygon.Triggers>
</Polygon>
</Canvas>
It's looking for a property of the Canvas called 'polygon', which in turn has a property called 'Stroke'. You need to use TargetName if you want the setter to target a different object.
<Setter TargetName="polygon" Property="Stroke" Value="#EEEEEE" />

Wpf: Storyboard.TargetName works, but Setter TargetName doesn't

Let's say we have a XAML code like this:
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border HorizontalAlignment="Center" VerticalAlignment="Center">
<Border.LayoutTransform>
<!--We are rotating randomly each image. Selected one will be rotated to 45°.-->
<RotateTransform Angle="{Binding RandomAngle}" x:Name="globalRotation"/>
</Border.LayoutTransform>
<Grid>
<Image Source="{Binding ImageLocation}" Stretch="None" />
<TextBlock x:Name="title" Text="{Binding Title}" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="title" Property="Visibility" Value="Visible"/>
<!--The next line will not compile.-->
<Setter TargetName="globalRotation" Property="Angle" Value="45"/>
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<!--This compiles well.-->
<DoubleAnimation Storyboard.TargetName="globalRotation" Storyboard.TargetProperty="Angle" To="45" Duration="00:00:03"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
This code is intended to display a set of images in a listbox. Each image has a random rotation, but when selected, rotates to 45 degrees.
Rotating selected image through a storyboard works well. I just specify Storyboard.TargetName and it rotates the image when selected (Trigger.ExitActions is omitted to make the code shorter).
Now, if I want, instead of using a storyboard, assign 45 degrees value directly, I can't do that, because <Setter TargetName="globalRotation" Property="Angle" Value="45"/>: it compiles with
"Cannot find the Trigger target 'globalRotation'. (The target must appear before any Setters, Triggers, or Conditions that use it.)"
error. What happens? I suppose that Storyboard.TargetName is evaluated during runtime, so let me compile it. Is it right?
How to make it work with just a setter, without using a storyboard?
The thing is that Trigger Setter can target only FrameworkElement or FrameworkContentElement objects, whereas Storyboard works with any DependencyProperty.
Here is a workaround:
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border x:Name="brd" HorizontalAlignment="Center" VerticalAlignment="Center" Tag="{Binding RandomAngle}">
<Border.LayoutTransform>
<!--We are rotating randomly each image. Selected one will be rotated to 45°.-->
<RotateTransform Angle="{Binding ElementName=brd, Path=Tag}" x:Name="globalRotation"/>
</Border.LayoutTransform>
<Grid>
<Image Source="{Binding ImageLocation}" Stretch="None" />
<TextBlock x:Name="title" Text="{Binding Title}" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="title" Property="Visibility" Value="Visible"/>
<!--The next line will not compile.-->
<Setter TargetName="brd" Property="Tag" Value="45"/>
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<!--This compiles well.-->
<DoubleAnimation Storyboard.TargetName="globalRotation" Storyboard.TargetProperty="Angle" To="45" Duration="00:00:03"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

WPF Trigger animation when Visibility is changed?

Well i have a custom control and when Visibility is changed to Visible I have a Trigger with a enter/exit action but the problem is that when the exit action fires the Visibility is no longer Visible so the animation can't be seen how would I fix this?
here is my Trigger:
<ControlTemplate.Triggers>
<Trigger Property="Visibility" Value="Visible">
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource Hide}"/>
</Trigger.ExitActions>
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource Show}"/>
</Trigger.EnterActions>
</Trigger>
</ControlTemplate.Triggers>
I tried this too and failed. I think it is not possible to accomplish this in a simple ControlTemplate with a Trigger on the Visibility property. What you can do is add an Opacity animation From 1 To 0 to a Trigger for a different property, for instance a DependencyProperty that you add in the code behind yourself.
You could also use ObjectAnimationUsingKeyFrames to set Visibility for animation period.
In such case there is no need in any codebehind.
There is a way to achieve it. Not 100 % pure, but works for me:
Don't use Visibility property, but use Opacity and Tag property.
<ListView.Resources>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Border CornerRadius="5"
BorderThickness="2"
BorderBrush="DodgerBlue"
Background="#CC4f9dea" >
<Grid>
<ContentPresenter HorizontalAlignment="Stretch" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Stretch" />
<Button x:Name="btnClose" Opacity="0" Content="X" Style="{StaticResource RoundedButtonStyle}"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Tag" TargetName="btnClose" Value="Visible" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.Resources>
<Style x:Key="RoundedButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border CornerRadius="15" Background="White" BorderThickness="1" Padding="2" BorderBrush="Black">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Tag" Value="Visible">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity"
From="0.0" To="0.5" Duration="0:0:0.5"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity"
From="0.5" To="0.0" Duration="0:0:0.5"/>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>

Resources