Context menuitems are not firing Click events - wpf

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

How to bind visibility of a control with context menu item IsChecked property?

(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

datatrigger cannot set bound property

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>

WPF: How to smoothly stop a rotation animation with the DataTrigger

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.

Change property on ListBox.SelectionChanged in XAML

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>

Animate from one style to another

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

Resources