I have a few grids which contains button and textblock inside each grids. I have grid style like this
<Style x:Key="SubSection_Grid_Style" TargetType="Grid">
<Setter Property="Margin" Value="0,5,0,5"/>
</Style>
I want to show which grid has been tapped or selected, and after tapping another grid, it should change state back to normal. I know how to set it like
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="SelectionBackground"
Storyboard.TargetProperty="Opacity"
Duration="0"
To="1" />
</Storyboard>
but not sure how to switch between select|unselect. Any idea?
Instead of trying to use the states of the grid. Try to write your own converter and bind the opacity or background to some Boolean variable.
<Grid Background="{Binding IsSomeGridShow, Converter={StaticResource BooleantoOpacityOrBackgroundConverter}}" >
<Button>
<TextBlock>
</Grid>
Related
I am creating a Style containing Animation's, which can then be inherited to specific control styles, which are applied automatically.
Actually I'm struggling on implementing a simple Animation:
When Visibility is changed to Visible, Opacity is changed from 0 to 1
When Visibility is changed to something else than visible, Opacity is doing the inverse thing
So far I got:
<Style x:Key="BaseAnimationsStyle">
<Style.Triggers>
<Trigger Property="FrameworkElement.Visibility" Value="Visible">
<Trigger.EnterActions> <!-- this works -->
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.5" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions><!-- this doesn't -->
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" To="0" Duration="0:0:0.5" />
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>
If the above Style is set on a control it then has the following behaviour:
When the control's Visibility is set to Visible the transition is working correctly, meaning it is fading in.
Issue:
When the control's Visibility is set to Hidden (or even Collapsed), the control will be hidden instantly without fading.
My guess is, that there is some default behaviour to be overridden of how FrameworkElement's deal with Visibility-Changes.
Setting the Visibility property to Collapsed or Hidden will make the element invisible right away but instead of setting the Visibility property you could set some attached property of yours and then animate the Opacity property to fade out the element. Please refer to the following link for more information and an example.
WPF: How To Animate Visibility Property?: http://blogs.microsoft.co.il/arik/2010/02/08/wpf-how-to-animate-visibility-property/ https://www.codeproject.com/Articles/57175/WPF-How-To-Animate-Visibility-Property
WPF Fade Animation
I have solved my issue with the information provided by #mm8's Answer.
Basically I added the VisibilityAnimation Class to my Project. I then simply created my Base-Style using the Provided Attached-Property inside a Setter.
<!-- Animations -->
<Style x:Key="BaseAnimationsStyle">
<Setter Property="anim:VisibilityAnimation.AnimationType" Value="Fade" />
</Style>
<!-- This adds the Visibility Animation to every Grid which has access to this resource -->
<Style TargetType="{x:Type Grid}" BasedOn="{StaticResource BaseAnimationsStyle}" />
Another Solution:
Create AttachedProperties for Visiblity. This enables you to set the Visibility of any control without having the Opacity set automatically.
If you want to use Bindings on the property, the first evaluation of the binding causes an animation, if the value is not Visibility.Visible. This is why another Property is needed, to specify another Visibility to start.
public static class AnimateableVisibility
{
public static readonly DependencyProperty VisibilityProperty = DependencyProperty.RegisterAttached(
"Visibility", typeof(Visibility), typeof(AnimateableVisibility), new PropertyMetadata(default(Visibility), VisibilityPropertyChanged));
private static void VisibilityPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var val = (Visibility) e.NewValue;
// Set StartVisibility to Visible when Visibility is set to Visible
if (val == Visibility.Visible)
d.SetCurrentValue(StartVisibilityProperty, val);
}
public static readonly DependencyProperty StartVisibilityProperty = DependencyProperty.RegisterAttached(
"StartVisibility", typeof(Visibility), typeof(AnimateableVisibility), new PropertyMetadata(default(Visibility)));
public static Visibility GetVisibility(DependencyObject obj)
{
return (Visibility)obj.GetValue(VisibilityProperty);
}
public static void SetVisibility(DependencyObject obj, Visibility value)
{
obj.SetValue(VisibilityProperty, value);
}
public static Visibility GetStartVisibility(DependencyObject obj)
{
return (Visibility)obj.GetValue(VisibilityProperty);
}
public static void SetStartVisibility(DependencyObject obj, Visibility value)
{
obj.SetValue(VisibilityProperty, value);
}
}
Now you can use those properties as follows:
<Grid>
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center" Orientation="Horizontal">
<Button Margin="5,0,15,0" Padding="7,0" Style="{StaticResource VisibilityAnimation}" utils:AnimateableVisibility.StartVisibility="Hidden"
utils:AnimateableVisibility.Visibility="{Binding ElementName=CheckBox, Path=IsChecked, Converter={StaticResource BoolToVisibilityConverter}}">I'm a Button</Button>
<CheckBox VerticalAlignment="Center" IsChecked="False" x:Name="CheckBox"></CheckBox>
</StackPanel>
</Grid>
By changing StartVisibility to Visible, you can see how the Button fades out on startup.
all thats missing now is the applied Style:
<Style x:Key="VisibilityAnimation">
<Style.Triggers>
<Trigger Property="utils:AnimateableVisibility.StartVisibility" Value="Hidden">
<!-- This avoids the Animation in cases when the first evaluation of AnimateableVisibility.Visibility is false -->
<Setter Property="UIElement.Visibility" Value="Hidden" />
</Trigger>
<Trigger Property="utils:AnimateableVisibility.Visibility" Value="Visible">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard TargetProperty="Opacity">
<DoubleAnimation To="1" Duration="0:0:2"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard TargetProperty="Opacity">
<DoubleAnimation To="0" Duration="0:0:2"/>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>
I want to create a custom style for buttons in my WPF application. I want to be able to change their Backgroound and BorderThickness properties when mouse is over them.
Some of the buttons are created dynamically in c# so I don't think that xaml solution will be enough.
I tried achieving my goal using Triggers and Setters in c#, but I couldn't get it to work, hover color always stayed light blue.
Here is how I'm creating buttons:
Button but = new Button()
{
Height = 40,
Background = new SolidColorBrush(Colors.Gray),
Content = new Label() {
FontSize = 13,
FontWeight = FontWeights.Medium,
Foreground = new SolidColorBrush(Colors.White)
}
}
stackPanel.Children.Add(but)
I know this is not the best way to create controls and I could probably be better off using MVVM, but I can't change the whole application so I'm just looking for a c# solution.
Thanks!
EDIT:
I added a style to App.xaml file. It looks like this (UpperMenuModeButton is my control based on regular button):
<Application.Resources>
<Style TargetType="UpperMenuModeButton" x:Key="UpperMenuModeButton" >
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
</Application.Resources>
I am setting the style while creating the button like this:
this.Style = (Style) Resources["UpperMenuModeButton"];
I am still getting regular light blue background on hover.
You can create a general style like this:
<Style TargetType="Button">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="FontFamily" Value="Comic Sans MS"/>
<Setter Property="FontSize" Value="14"/>
<EventTrigger RoutedEvent="Mouse.MouseEnter">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Duration="0:0:0.2"
Storyboard.TargetProperty="MaxHeight"
To="90" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent="Mouse.MouseLeave">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Duration="0:0:1"
Storyboard.TargetProperty="MaxHeight" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style>
Put this code in the scope of your buttons (in it's page or grid or container) and it'll work automatically.
For more info see here
Edit
For your problem regarding button hover events see here
For that style to work on a normal button you need to set the TargetType to Button. Otherwise it will not be applied. Hope this helps.
I'm having a really hard time finding a way to do the following...
I have my "Image button style," and it is applied to every button in my Silverlight app. Is there any way to make a blanket VisualStateManager to change the image on MouseOver, that will work for every button? I have a couple ideas, but I'm not sure if they can be implemented...
Let's say my button image paths are consistent:
image1.png
image2.png
and
image1 - hover.png
image2 - hover.png
Is there a way to change the path of the image to append " - hover"? I thought about using an IValueConverter for this, but wasn't sure how to access the control state...
An alternative idea I had was if there was a way to accomplish this:
<Button>
<Image Source="../Images/image1.png" Width="70"/>
<Image Source="../Images/image1 - hover.png" Width="70"/>
</Button>
Have two contents (an array of content?) and on Normal state, set only the first content opacity to 1, and the rest to 0. Then on MouseOver, switch the opacities.
Are any of these solutions feasible, and how can they be implemented?
Thanks
Edit: I know I can make custom styles for each button that switch out their images, but I would like a blanket style that I can apply to all buttons.
You may (ab)use the Tag property for your purpose and create a ControlTemplate with two Image controls with a BitmapImage that binds its UriSource property to either the Content or the Tag property respectively:
<Style TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="CommonStates">
<VisualState Name="Normal"/>
<VisualState Name="MouseOver">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="image1"
Storyboard.TargetProperty="Opacity"
To="0" Duration="0:0:0.1"/>
<DoubleAnimation
Storyboard.TargetName="image2"
Storyboard.TargetProperty="Opacity"
To="1" Duration="0:0:0.1"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Image x:Name="image1">
<Image.Source>
<BitmapImage UriSource="{Binding Content,
RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
</Image.Source>
</Image>
<Image x:Name="image2" Opacity="0">
<Image.Source>
<BitmapImage UriSource="{Binding Tag,
RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
</Image.Source>
</Image>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Now you may declare a Button like this:
<Button Content="../Images/image1.png" Tag="../Images/image1_hover.png"/>
I have a ListBox in WPF which is binded using an XMLDataProvider which points to an xml File.
I have a storyboard set in the itemtemplate of my ListBoxItem as such:
<Setter Property="LayoutTransform">
<Setter.Value>
<ScaleTransform x:Name="transform" />
</Setter.Value>
</Setter>
<Style.Triggers>
<EventTrigger RoutedEvent="Loaded">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:.2" />
<DoubleAnimation Storyboard.TargetProperty="LayoutTransform.ScaleY" From="0" Duration="0:0:.2" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
This works great when the file is first loaded on starting the application. However when I add a new XMl element to the list like this:
MainNode.AppendChild(NewElement)
The element is added to the list but the storyboard does not fire. How can I make sure the programatically added item calls the "Loaded" event onto itself?
UPDATE: The style was applied to ListBox instead of ListBoxItem. Changing solved the question.
As mentioned in the comments Style should be applied on ListBoxItem which will be raised for every new ListBoxItem add.
ListBox loaded event will be raised only when it gets loaded on UI first time and not afterwards. So, move the style from ListBox to ListBoxItem.
I have WP7 application with simple phone page.
I have check box
<CheckBox Content="Click me" Margin="0,2,0,0">
When I check the checkbox I want Stack panel below it to expand.
<StackPanel Height="0" x:Name="MyStackPanel">
<CheckBox Content="Condition"/>
</StackPanel>
Right now I tried this solution, but i receive exception that EventTrigger.RoutedEvent cannot be assign to Checkbox.Checked.
<CheckBox Content="Click Me" Margin="0,2,0,0">
<CheckBox.Triggers>
<EventTrigger RoutedEvent="CheckBox.Checked">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="MyStackPanel"
Storyboard.TargetProperty="Height"
To="100"
Duration="0:0:0.5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</CheckBox.Triggers>
</CheckBox>
Do you have any ideas what is the best approach to implement such animation?
Thanks
There is a control for what you require to do. You should be using the Expander control that iss part of the silverlight toolkit . There iS A good two part tutorial about working with this control here on WindowsPhoneGeek.
Basically, you use the expander control and implement your own custom controls for the header and the items.
try ToggleButton.Checked instead of CheckBox.Checked