Storyboard label style how to apply background when datatrigger false? - c#

I have a simple for with a set of labels on a grid, i have added a label style storyboard for flashing when NodeFlash is set to true and this works fine, however when NodeFlash set to false the label remains white background / white text and not the background color set in NodeStatus ( ie green, red etc ). where would i need to force the background color setting in the exit actions or else where?
heres the view.xaml
<Grid>
<ItemsControl ItemsSource = "{Binding Path = CIs}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Label
Content = "{Binding Path = NodeName, Mode = OneWay}"
Background = "{Binding Path = NodeStatus, Mode = OneWay}"
Tag="{Binding Path = Nodeid, Mode = OneWay}"
Foreground="White"
FontFamily="Arial Black"
HorizontalContentAlignment="Center"
BorderBrush="Black"
BorderThickness="1,1,1,1">
<Label.Style>
<Style TargetType="{x:Type Label}">
<Style.Resources>
<Storyboard x:Key="flashAnimation" >
<DoubleAnimation Storyboard.TargetProperty="Opacity" From="1" To="0" AutoReverse="True" Duration="0:0:0.5" RepeatBehavior="Forever" />
</Storyboard>
</Style.Resources>
<Setter Property="Visibility" Value="Hidden" />
<Style.Triggers>
<DataTrigger Binding="{Binding NodeFlash}" Value="True">
<Setter Property="Visibility" Value="Visible" />
<DataTrigger.EnterActions>
<BeginStoryboard Name="flash" Storyboard="{StaticResource flashAnimation}" />
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="flash"/>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
Thanks again

found it i think? i need to change this:
<Setter Property="Visibility" Value="Hidden" />
to
<Setter Property="Visibility" Value="Visible" />
think it was hiding all non styled labels?
Thanks

Related

WPF colorAnimation border brush color throws 'System.Windows.Markup.XamlParseException'

I'm trying to implement color animation on border brush with Style.Triggers.
The ViewModel changes the collection which each Border color is bounded.
I guess the UI elements are not initialized but the condition is fulfilled and then the exception is thrown:
"Additional information: Cannot resolve all property references in the property path 'BorderBrush.Color'. Verify that applicable objects support the properties."
Here the View.cs.xaml code:
<HierarchicalDataTemplate DataType="{x:Type model:SchemaNode}"
ItemsSource="{Binding Children}">
<Border CornerRadius="40">
<Border.Style>
<Style TargetType="Border">
<Setter Property="Background" Value="{DynamicResource MaterialDesignPaper}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Closed}" Value="True">
<Setter Property="Background" Value="{Binding Outline}" />
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<Border.InputBindings>
<MouseBinding MouseAction="LeftDoubleClick"
Command="{Binding OnDoubleClick}" CommandParameter="{Binding GlobalId}"/>
</Border.InputBindings>
<Border.ContextMenu>
<ContextMenu ItemsSource="{Binding ContextActions}" Width="150" Placement="Mouse">
<ContextMenu.ItemTemplate>
<DataTemplate DataType="{x:Type helper:ContextAction}">
<MenuItem Header="{Binding Header}" Command="{Binding Command}"/>
</DataTemplate>
</ContextMenu.ItemTemplate>
</ContextMenu>
</Border.ContextMenu>
<Border BorderThickness="3" CornerRadius="360"
BorderBrush="{Binding Outline}" Width="{Binding Width}" Height="{Binding Height}">
<Border.Style>
<Style TargetType="Border">
<Style.Triggers>
<DataTrigger Binding="{Binding Located}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard x:Name="LocatedBeginStoryBoard">
<Storyboard Duration="0:0:0.5" RepeatBehavior="Forever" AutoReverse="True">
<ThicknessAnimation Storyboard.TargetProperty="BorderThickness" Duration="0:0:0.4"
FillBehavior="HoldEnd"
To="5"/>
<ThicknessAnimation Storyboard.TargetProperty="BorderThickness"
FillBehavior="HoldEnd"
BeginTime="0:0:0.4"
To="5"/>
<ColorAnimation Storyboard.TargetProperty="BorderBrush.Color"
To="White"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<RemoveStoryboard BeginStoryboardName="LocatedBeginStoryBoard"/>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<Image Height="50"
Width="50" Source="{Binding ImageSource, Converter={StaticResource imagePathToImageConverter}}"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Image.InputBindings>
<MouseBinding MouseAction="LeftDoubleClick" Command="{Binding OnDoubleClick}" CommandParameter="{Binding GlobalId}"/>
</Image.InputBindings>
</Image>
</Border>
</Border>
</HierarchicalDataTemplate>
Hopefully I have provided enough code do resolve this problem.
Most likely the BorderBursh you bind via Outline is not a SolidColorBrush but a GradientBrush or simply unassigned and therefore doesn't have a Color property.
You can test this by assigning a SolidColorBrush (directyl or via style).
<Style TargetType="Border">
<Style.Setters>
<Setter Property="BorderBrush" Value="Blue"/>
</Style.Setters>
<!-- etc -->

Using a Storyboard on a ToolTip WPF

I am trying to create a storyboard, so when a user clicks on a textbox, its copies the text to their clipboard and shows a tooltip saying copied, which then fades away.
Here is my attempt:
xaml:
<TextBox Name="PolyValue" Text="{Binding .}" IsReadOnly="True" BorderThickness="0" Background="White"
VerticalAlignment="Center" PreviewMouseDown="CopyTextBox" >
<TextBox.ToolTip>
<ToolTip Style="{StaticResource TooltipPopupFadeAway}" IsOpen="True" Opacity="0" Background="Transparent" BorderThickness="0">
<Border Background="White" BorderBrush="Black" BorderThickness="1" CornerRadius="3" >
<Label Content="Copied" Padding="5, 2" />
</Border>
</ToolTip>
</TextBox.ToolTip>
</TextBox>
Here is the Storyboard:
<Style x:Key="TooltipPopupFadeAway" TargetType="ToolTip">
<Style.Triggers>
<DataTrigger Binding="{Binding Opacity, RelativeSource={RelativeSource Self}}" Value="1">
<DataTrigger.EnterActions>
<BeginStoryboard x:Name="ClosePopupStoryBoard">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" Duration="00:00:01" From="3" To="0" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
Code behind:
private void CopyTextBox(object sender, MouseButtonEventArgs e)
{
if(sender is TextBox textBox)
{
Clipboard.SetText(textBox.Text);
(textBox.ToolTip as ToolTip).IsOpen = false;
(textBox.ToolTip as ToolTip).IsOpen = true; //this recalculates the position
(textBox.ToolTip as ToolTip).Opacity = 1;
}
}
This works exactly how I want it to, however it only works once, after it has been shown and the user clicks again nothing happens.
After setting a break point in the CopyTextBox method, the of the ToolTip opacity is 0 even after programmatically setting it to 1.
I am not sure what I am doing wrong?
This is the sort of approach I mean.
Just binding the text property means you need no code.
I'm not sure this does exactly what you want because you seem to have previewmousedown showing the tooltip. Which is a bit odd for a tooltip since mouseover shows them.
<Window.Resources>
<ControlTemplate x:Key="TooltipPopupFadeAway" TargetType="ToolTip">
<Border Background="Yellow">
<TextBlock Text="{Binding PlacementTarget.Text, RelativeSource={RelativeSource AncestorType={x:Type ToolTip}}}"
Name="TheText"
/>
</Border>
<ControlTemplate.Triggers>
<EventTrigger RoutedEvent="ToolTip.Opened">
<BeginStoryboard>
<Storyboard TargetProperty="Opacity">
<DoubleAnimation From="1.0" To="0" Duration="0:0:2" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Window.Resources>
<Grid>
<TextBox>
<TextBox.ToolTip>
<ToolTip Template="{StaticResource TooltipPopupFadeAway}"/>
</TextBox.ToolTip>
</TextBox>
</Grid>
And you could set that template and tooltip etc via style if it suited you better. I used a yellow background so I can see it easy. The tooltip probably doesn't exactly match what you had.
You should trigger directly on the IsOpen property. Make sure to set the default Opacity to 0, and do not explicitly set it to 1 afterwards.
<Style x:Key="TooltipPopupFadeAway" TargetType="ToolTip">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Opacity" Value="0"/>
<Setter Property="IsOpen" Value="False"/>
<Style.Triggers>
<Trigger Property="IsOpen" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity"
Duration="0:0:1" From="3" To="0"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
In code behind, do not to set the Opacity:
private void CopyTextBox(object sender, MouseButtonEventArgs e)
{
if (sender is TextBox textBox)
{
Clipboard.SetText(textBox.Text);
((ToolTip)textBox.ToolTip).IsOpen = false;
((ToolTip)textBox.ToolTip).IsOpen = true;
}
}

(WPF App C#) Change color only on pressed event and back to original color on release?

I got a code that change the color to yellow of a button when i pressed, the problem is not going back to original color when i release, any solution?
<Button Content="0" FontSize="28" FontWeight="Bold" Height="53" HorizontalAlignment="Left" Margin="67,51,0,0" Name="button10" VerticalAlignment="Top" Width="63" Grid.Column="9" Grid.Row="5" Grid.ColumnSpan="3" Grid.RowSpan="2">
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<Trigger Property="IsPressed" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="(Button.Background).(SolidColorBrush.Color)" To="Yellow"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
If you're not actually doing any animation, you can dispense with the storyboard:
<Style TargetType="Button">
<Style.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="Yellow" />
</Trigger>
</Style.Triggers>
</Style>
This will revert to the previous background color when the condition is no longer true. But it only works if the existing background color is set by a Style Setter -- if you put in a Background="Purple" attribute on the Button, the style can't touch the background color.
How about
<Trigger Property="IsPressed" Value="False">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="(Button.Background).(SolidColorBrush.Color)" To="OriginalColor"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>

Stop wpf Storyboard and hold actual value

I have following wpf code
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<Image x:Key="MyImage" Source="../Assets/icon.ico"/>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
<Storyboard x:Key="AkomiLogoAnimation">
<DoubleAnimation
Storyboard.TargetProperty="(Image.RenderTransform).(RotateTransform.Angle)"
By="360"
SpeedRatio="0.5"
RepeatBehavior="Forever"
FillBehavior="Stop"
/>
</Storyboard>
</ResourceDictionary>
</Window.Resources>
<TextBox x:Name="txtAuto"/>
<Image Source="../Assets/icon.ico" Width="20" Height="20" RenderTransformOrigin=".5,.5">
<Image.Resources>
<converter:IsNullConverter x:Key="IsNullConverter"/>
</Image.Resources>
<Image.RenderTransform>
<RotateTransform Angle="0" />
</Image.RenderTransform>
<Image.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=txtAuto, Path=Text, Converter={StaticResource IsNullConverter}, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}" Value="False">
<DataTrigger.EnterActions>
<BeginStoryboard Name="AkomiRotation" Storyboard="{StaticResource AkomiLogoAnimation}">
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=txtAuto, Path=Text, Converter={StaticResource IsNullConverter}, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}" Value="True">
<DataTrigger.EnterActions>
<StopStoryboard BeginStoryboardName="AkomiRotation" >
</StopStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
The goal is to rotate the image as soon as some text has been entered. But stopping the storyboard lets the image angle jump into it's initial value.
I tried to add FillBehavior="HoldEnd" to the Storyboard definition, but that doesn't work.
Any suggestions? Maybe I can access the angle-value at the end of the animation anyhow and set this value in RotateTransform
Have you tried PauseStoryboard, instead of stop? Also, you should change fillbehavior on the animation

In WPF, how to do when EventTrigger Source is outside a page's resources but Storyboard.TargetName is in a treeview datatemplate?

I have a TreeView whose <ItemTemplate> is defined in HierarchicalDataTemplate
<HierarchicalDataTemplate ItemsSource="{Binding}"
x:Key="TreeTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Name="TextBlockProperty" Text="{Binding Name}" Width="110" Foreground="#FF3C3C3C" >
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding ModifyType}" Value="AutoDetect">
<Setter Property="Background">
<Setter.Value>
<SolidColorBrush Color="LightGreen"></SolidColorBrush>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding ModifyType}" Value="Prerequisite">
<Setter Property="Background">
<Setter.Value>
<SolidColorBrush Color="LightSkyBlue"></SolidColorBrush>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding ModifyType}" Value="AutoCheckFailed">
<Setter Property="Background">
<Setter.Value>
<SolidColorBrush Color="Red"></SolidColorBrush>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<ContentControl Name="ContentCtrl" Content="{Binding}">
</ContentControl>
</StackPanel>
<HierarchicalDataTemplate.Triggers>
<DataTrigger Binding="{Binding ControlType}" Value="Text">
<Setter TargetName="ContentCtrl" Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBox Width="130" Text="{Binding Value}" BorderThickness="0" Background="#FFF8F8F8"></TextBox>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding ControlType}" Value="Choice">
<Setter TargetName="ContentCtrl" Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<ComboBox Width="130" IsEditable="True" ItemsSource="{Binding ChoiceItems}" Text="{Binding Value}" BorderThickness="0" >
</ComboBox>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding ControlType}" Value="Group">
<Setter TargetName="ContentCtrl" Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock></TextBlock>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</HierarchicalDataTemplate.Triggers>
</HierarchicalDataTemplate>
I have also defined 2 <Buttons> ShowDefault and HideDefault outside the <Page.Resources> to shorten/widen the width of the TextBlockProperty <TextBlock> in the <HierarchicalDataTemplate> by using Storyboard. But I don't know how to do it.
Because it is a TreeView, the Items are actually several columns and rows, more like a form, binded in the <HierarchicalDataTemplate>. But the 2 Buttons are defined in a Grid outside the <Page.Resources>...In order to do the Width shortening/widening, I use Storyboard in <Page.Resources>.
<Storyboard x:Key="ShowDefault">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Width" Storyboard.TargetName="GroupList">
<EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Width" Storyboard.TargetName="PropertyTree">
<EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="270"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Width" Storyboard.TargetName="DefaultTree">
<EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="182"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="HideDefault">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Width" Storyboard.TargetName="GroupList">
<EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="152"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Width" Storyboard.TargetName="PropertyTree">
<EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="299"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Width" Storyboard.TargetName="DefaultTree">
<EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
And call the Storyboard like this:
<Page.Triggers>
<EventTrigger RoutedEvent="ButtonBase.Click" SourceName="ShowDefaultValue">
<BeginStoryboard Storyboard="{StaticResource ShowDefault}"/>
</EventTrigger>
<EventTrigger RoutedEvent="ButtonBase.Click" SourceName="HideDefaultValue">
<BeginStoryboard Storyboard="{StaticResource HideDefault}"/>
</EventTrigger>
</Page.Triggers>
A little complicated, but hope you get it right.
Any help or suggestions will be appreciated. :)
I'm not sure what are you trying to achieve, so I must guess what you meant :).
To get the reference to the TextBlock you can attached to its Loaded event like this:
<TextBlock Loaded="TextBoxLoaded"></TextBlock>
private TextBlock _textBlock;
private void TextBoxLoaded(object sender, RoutedEventArgs e)
{
_textBlock = sender as TextBlock;
}
and then when the button is clicked, changed the properties of the TextBlock.
Normally, the button should be in the template as well for each item of your child template.
OK, I eventually solve the problem by adding a <ScrollView> outside the <StackPanel> of two <TreeView>s. No need to change the DataBinding or anything else.

Categories

Resources