I tried to open the ContextMenu on button left click not on the right clcik so I did something as below. But menu items 'All' and 'Selected' are not firing their respective events in .cs.
Xaml
<Button Content="Import" ContextMenuService.IsEnabled="false">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Style.Triggers>
<EventTrigger RoutedEvent="Click">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="ContextMenu.IsOpen">
<DiscreteBooleanKeyFrame KeyTime="0:0:0" Value="True"/>
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu>
<MenuItem Header="All"
Click="ImportAll_Click"/>
<MenuItem Header="Selected"
Click="ImportSelected_Click"/>
</ContextMenu>
</Setter.Value>
</Setter>
</Style>
</Button.Style>
</Button>
Xaml.cs
private void ImportAll_Click(object sender, RoutedEventArgs e)
{
}
private void ImportSelected_Click(object sender, RoutedEventArgs e)
{
}
Is there something that I am missing here?
Try to define the ContextMenu as a resource:
<Button Content="Import" ContextMenuService.IsEnabled="false">
<Button.Resources>
<ContextMenu x:Key="cm">
<MenuItem Header="All" Click="ImportAll_Click"/>
<MenuItem Header="Selected" Click="ImportSelected_Click"/>
</ContextMenu>
</Button.Resources>
<Button.Style>
<Style TargetType="{x:Type Button}">
<Style.Triggers>
<EventTrigger RoutedEvent="Click">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="ContextMenu.IsOpen">
<DiscreteBooleanKeyFrame KeyTime="0:0:0" Value="True"/>
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
<Setter Property="ContextMenu" Value="{StaticResource cm}" />
</Style>
</Button.Style>
</Button>
Related
(On clicking the menu item , the visibility of the textblock mentioned below should be changed, How can i achieve this using data binding)
**<MenuItem Header="Lat/Long Info" IsCheckable="True" IsChecked="True"/>**
</ContextMenu>
</Window.Resources>
<Grid>
<Button Content="MENU" Height="20" Width="100" Margin="0,10" HorizontalAlignment="Left" VerticalAlignment="Top">
<Button.LayoutTransform>
<RotateTransform Angle="-90"/>
</Button.LayoutTransform>
<Button.Style>
<Style TargetType="Button">
<Setter Property="Button.Background" Value="Black"/>
<Setter Property="Button.Foreground" Value="White"/>
<Setter Property="ContextMenu" Value="{StaticResource conmenu}"/>
<Style.Triggers>
<EventTrigger RoutedEvent="Click">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="ContextMenu.IsOpen">
<DiscreteBooleanKeyFrame KeyTime="0:0:0" Value="True"/>
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
**<TextBlock Text="Change my Visibility" Margin="50"></TextBlock>**
</Grid>
Please anyone help me with this issue , I am unable to find any solution
I have 2 checkboxes (chkMfsUi and chkMfs). When I check chkMfsUi, I also want to check chkMfs (and disable it).
I tried it with a datatrigger:
<Style x:Key="MfsCheckBoxStyle" TargetType="CheckBox">
<Setter Property="IsEnabled" Value="True" />
<Setter Property="IsChecked" Value="False" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=chkMfsUi}" Value="True">
<Setter Property="IsEnabled" Value="False" />
<Setter Property="IsChecked" Value="True" />
</DataTrigger>
</Style.Triggers>
</Style>
And these are my checkboxes:
<StackPanel>
<CheckBox Name="chkMfsUi"
Checked="CheckBox_Checked"
Content="MFS - UI"
IsChecked="{Binding MfsUi}"
Unchecked="CheckBox_Checked" />
<CheckBox Content="MFS" IsChecked="{Binding Mfs}" Style="{StaticResource MfsCheckBoxStyle}" />
</StackPanel>
The IsEnabled property work fine, but the IsChecked doesn't. Maybe because it is bound? I am also using INotifyPropertyChanged with these properties.
If I set it in code behind, it works, but is it possible with a trigger though?
Regards,
Alfons
EDIT:
As appeared from the current answers, my question seems to be incomplete. I need to have the following three states:
AND last but not least: Both checkboxes' IsChecked properties must be bound! (This is the moment when the trouble comes in)
Try this
<StackPanel Grid.Column="1">
<CheckBox x:Name="chkMfsUi" IsChecked="True"></CheckBox>
<CheckBox x:Name="chkMfs" IsChecked="{Binding ElementName=chkMfsUi,Path=IsChecked}">
<CheckBox.Style>
<Style TargetType="CheckBox">
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="IsEnabled" Value="False"/>
</Trigger>
</Style.Triggers>
</Style>
</CheckBox.Style>
</CheckBox>
Another Method : By using style in resource
Add this namespace first xmlns:Globalvaribale="clr-namespace:System;assembly=mscorlib"
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Globalvaribale="clr-namespace:System;assembly=mscorlib">
<Window.Resources>
<Globalvaribale:String x:Key="chkMfsUi">chkMfsUi</Globalvaribale:String>
<Style x:Key="chkMfsstyle" TargetType="CheckBox">
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked,ElementName={StaticResource chkMfsUi}}" Value="True">
<Setter Property="IsEnabled" Value="False"/>
<Setter Property="IsChecked" Value="True"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel Grid.Column="1">
<CheckBox x:Name="chkMfsUi"></CheckBox>
<CheckBox Style="{StaticResource chkMfsstyle}"/>
</StackPanel>
Output
In this case you can use the EventTrigger:
Represents a trigger that applies a set of actions in response to an event.
Example:
<StackPanel>
<StackPanel.Triggers>
<EventTrigger RoutedEvent="CheckBox.Checked" SourceName="First">
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetName="Second"
Storyboard.TargetProperty="IsChecked">
<DiscreteBooleanKeyFrame KeyTime="00:00:00" Value="True" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="CheckBox.Checked" SourceName="Second">
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetName="First"
Storyboard.TargetProperty="IsChecked">
<DiscreteBooleanKeyFrame KeyTime="00:00:00" Value="True" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="CheckBox.Unchecked" SourceName="First">
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetName="Second"
Storyboard.TargetProperty="IsChecked">
<DiscreteBooleanKeyFrame KeyTime="00:00:00" Value="False" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="CheckBox.Unchecked" SourceName="Second">
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetName="First"
Storyboard.TargetProperty="IsChecked">
<DiscreteBooleanKeyFrame KeyTime="00:00:00" Value="False" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</StackPanel.Triggers>
<CheckBox Name="First"
Content="First" />
<CheckBox Name="Second"
Content="Second" />
</StackPanel>
The Storyboard can be stored in Resources for readability, like so:
<Window.Resources>
<Storyboard x:Key="FirstCheckedStory" ... />
</Window.Resources>
And then use like this:
<EventTrigger RoutedEvent="CheckBox.Checked" SourceName="First">
<BeginStoryboard Storyboard="{StaticResource FirstCheckedStory}" />
</EventTrigger>
Also, the Storyboard can contain several actions, just put him in order:
<Storyboard>
<BooleanAnimationUsingKeyFrames ... />
<BooleanAnimationUsingKeyFrames ... />
</Storyboard>
The animation hardly stops and the image resets its position but I want the animation to finish to the next full 360°.
Any ideas on that?
The XAML code:
<Button
BorderThickness="0"
Cursor="Hand"
Command="{Binding RefreshCommand}">
<Button.Template>
<ControlTemplate TargetType="Button">
<Border>
<ContentPresenter />
</Border>
</ControlTemplate>
</Button.Template>
<Image Source="../Resources/RefreshIcon.png">
<Image.Style>
<Style>
<Setter Property="Image.RenderTransform">
<Setter.Value>
<RotateTransform />
</Setter.Value>
</Setter>
<Setter Property="Image.RenderTransformOrigin" Value=".5,.5">
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding IsRefreshing}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard Name="RotationStoryboard">
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="RenderTransform.Angle"
From="0"
To="360"
Duration="0:0:0.8"
RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
<DataTrigger Binding="{Binding IsRefreshing}" Value="False">
<DataTrigger.EnterActions>
<RemoveStoryboard BeginStoryboardName="RotationStoryboard"/>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</Button>
The final solution except the fact that it has to be put into a UserControl to make it more generic (also see #Sheridans post and my comment below):
<Button
BorderThickness="0"
Cursor="Hand"
Command="{Binding RefreshCommand}">
<Button.Template>
<ControlTemplate TargetType="Button">
<Border>
<ContentPresenter />
</Border>
</ControlTemplate>
</Button.Template>
<Image
Name="RefreshImage"
Source="../Resources/RefreshIcon.png"
RenderTransformOrigin=".5,.5">
<Image.Resources>
<Storyboard
x:Key="RotationStoryboard"
Completed="RotationStoryboardCompleted">
<DoubleAnimation
Storyboard.Target="{Binding ElementName=RefreshImage}"
Storyboard.TargetProperty="RenderTransform.Angle"
From="0"
To="360"
Duration="0:0:1.5">
<DoubleAnimation.EasingFunction>
<CircleEase EasingMode="EaseInOut"></CircleEase>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</Image.Resources>
<Image.Style>
<Style>
<Setter Property="Image.RenderTransform">
<Setter.Value>
<RotateTransform />
</Setter.Value>
</Setter>
<Setter Property="Image.RenderTransformOrigin" Value=".5,.5">
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding IsRefreshing}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<StaticResource ResourceKey="RotationStoryboard"/>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</Button>
Code behind:
public partial class SomeView
{
public SomeView()
{
InitializeComponent();
}
private void RotationStoryboardCompleted(object sender, EventArgs e)
{
var viewModel = (ISomeViewModel)DataContext;
var storyboard = (Storyboard)((ClockGroup)sender).Timeline;
if (viewModel.IsRefreshing)
{
storyboard.Begin();
}
}
}
I don't know of any way to do this in XAML, but with code, there is a Timeline.Completed Event that you can use. If you attach a handler to your Storyboard, then it will get called when it is finished and you can do whatever you want:
<BeginStoryboard>
<Storyboard Name="RotationStoryboard" Completed="StoryboardCompleted">
<DoubleAnimation Storyboard.TargetProperty="RenderTransform.Angle" From="0"
To="360" Duration="0:0:0.8" />
</Storyboard>
</BeginStoryboard>
In code:
private void StoryboardCompleted(object sender, EventArgs e)
{
// Restart your Storyboard here each time until you want it to stop.
}
For further help, please see the example in the linked page on MSDN.
I want to write XAML code to change color of button when user changes selectionIndex of ListBox. How can I do it? I try
<Trigger Property="IsSelectionChanged" Value="True">
<Setter TargetName="btnSave" Property="Background" Value="Red" />
</Trigger>
But property IsSelectionChanged is not found.
There is no such property, you need to use an EventTrigger:
<Button Name="buton" Content="The Buton"/>
<ListBox ItemsSource="{Binding Data}">
<ListBox.Style>
<Style TargetType="{x:Type ListBox}">
<Style.Triggers>
<EventTrigger RoutedEvent="SelectionChanged">
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.Target="{x:Reference buton}"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Brushes.Red}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
</ListBox.Style>
</ListBox>
Just wondering if anyone know how to animate from one style to another i.e. going from NormalStyle to ActiveStyle when the user focuses on the textbox
<Style x:key="NormalStyle" TargetType="{x:Type TextBox}">
<Setter Property="BorderBrush" Value="Gray" />
<Setter Property="BorderThickness" Value="2" />
</Style>
<Style x:key="ActiveStyle" TargetType="{x:Type TextBox}" BasedOn="{StaticResource NormalStyle}">
<Setter Property="BorderBrush" Value="Green" />
<Setter Property="BorderThickness" Value="4" />
</Style>
If you want to swap the whole style, I think you might have to do it in code:
<StackPanel>
<TextBox Style="{StaticResource NormalStyle}" GotFocus="TextBox_GotFocus" LostFocus="TextBox_LostFocus"/>
<TextBox Style="{StaticResource NormalStyle}" GotFocus="TextBox_GotFocus" LostFocus="TextBox_LostFocus"/>
</StackPanel>
private Style focusedStyle;
private Style normalStyle;
public MainWindow()
{
InitializeComponent();
focusedStyle = FindResource("ActiveStyle") as Style;
normalStyle = FindResource("NormalStyle") as Style;
}
private void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
((TextBox)sender).Style = focusedStyle;
}
private void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
((TextBox)sender).Style = normalStyle;
}
Otherwise, you are pretty much confined to triggering back and forth..
<TextBox Text="1" >
<TextBox.Style>
<Style BasedOn="{StaticResource NormalStyle}" TargetType="{x:Type TextBox}">
<Style.Triggers>
<EventTrigger RoutedEvent="GotFocus">
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="BorderBrush.Color" To="Green" Duration="0:0:0.1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="LostFocus">
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="BorderBrush.Color" To="Gray" Duration="0:0:0.1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
</TextBox.Style