I have the following context menu on the header of a column in a datagridview.
<DataGridCheckBoxColumn Binding="{Binding Include,UpdateSourceTrigger=PropertyChanged}" Width="50">
<DataGridCheckBoxColumn.HeaderTemplate>
<DataTemplate>
<TextBlock Text="Export">
<TextBlock.ContextMenu>
<ContextMenu>
<MenuItem Header="Alle auswaehlen"/>
<MenuItem Header="Alle abwahelen"/>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</DataTemplate>
</DataGridCheckBoxColumn.HeaderTemplate>
</DataGridCheckBoxColumn>
As you can see, the context menu is static. How can I map the Command attribute to static methods in my code? All examples I found online were for flexible binding or for cut/copy.
You could use the click event instead:
<MenuItem Header="Alle auswaehlen" Click="MenuItem_Click_1"/>
And then have this method in your code:
private void MenuItem_Click_1(object sender, RoutedEventArgs e)
{
}
I don't see why that ContextMenu would be static; it appears to be created for each text block, which will be created for each header. If you only have one header, then I suppose it's de facto static.
Either way, if you want to bind to static command MyCommand of class MyNamespace.MyClass, then you use the following syntax:
<MenuItem Header="header" Command="{x:Static mynamespace:MyClass.MyCommand}"/>
Note that you need to have specified the xml namespace on the parent XAML object as follows:
xmlns:mynamespace="clr-namespace:MyNamespace"
Related
I am building a dynamic context menu. To make that happen I have come up with a custom viewmodel that represents my contextmenu, defined like this:
public class ContextMenuVM {
public object ContextItem { get; set; }
public ObservableCollection<ICommand> Items { get; private set; }
}
The property Items holds the effective commands to show in the contextmenu and the property ContextItem holds the context-item that these commands are to be executed on.
Further, I have a singleton class which holds all my various commands and their implementation. So in the end there will be a method that will be called UpdateContextMenu on the viewmodel that owns the contextmenu that does something like this:
ContextMenu.Items.Clear();
ContextMenu.Items.Add(SingletonClass.Instance.CommandA);
if (condition)
ContextMenu.Items.Add(SingletonClass.Instance.CommandB);
The ContextMenu iteself in XAML is defined like this:
<ContextMenu ItemsSource="{Binding Path=ContextMenu.Items}">
<ContextMenu.ItemTemplate>
<DataTemplate>
<ContentControl>
<MenuItem Command="{Binding}" CommandParameter="what-goes-here?" />
</ContentControl>
</DataTemplate>
</ContextMenu.ItemTemplate>
</ContextMenu>
What I fail to achieve is getting the CommandParameter binding to work. How am I supposed to bind to the ContextItem property of the ContextMenuVM instance?
Without a good Minimal, Complete, and Verifiable code example that clearly shows what you're doing, it's impossible to know for sure. But based on the information you've provided so far, it seems like you are looking for the RelativeSource binding source. E.g.:
<ContextMenu ItemsSource="{Binding Path=ContextMenu.Items}">
<ContextMenu.ItemTemplate>
<DataTemplate>
<ContentControl>
<MenuItem Command="{Binding}"
CommandParameter="{Binding ContextMenu.ContextItem
RelativeSource={RelativeSource AncestorType=ContextMenu}}"/>
</ContentControl>
</DataTemplate>
</ContextMenu.ItemTemplate>
</ContextMenu>
I had to make a guess as to the binding path, based on your ItemsSource binding, because your original code example isn't complete. The basic idea is to bind to a path that is relative to the specified source, so I've assumed that the ContextMenu refers to a property that returns the ContextMenuVM object you are using.
If this doesn't address your question, please improve it by providing a good MCVE.
I want to have custom Commands to respond to in my application.
So I was following the instructions on this answer, and created a static class for my commands:
namespace MyNamespace {
public static class Commands {
public static readonly RoutedUICommand Create = new RoutedUICommand(
"Create Thing", nameof(Create),
typeof(MyControl)
);
}
}
I then tried using it on my UserControl:
<UserControl x:Class="MyNamespace.MyControl"
...boilerplate...
xmlns:local="clr-namespace:MyNamespace">
<UserControl.CommandBindings>
<CommandBinding Command="local:Commands.Create"
CanExecute="CanCreateThing"
Executed="CreateThing"/>
</UserControl.CommandBindings>
...the control's contents...
</UserControl>
The method CanCreateThing always sets CanExecute to true. CreateThing currently does nothing.
I get this error on the usage of MyControl in the window XAML:
Type reference cannot find type named '{clr-namespace:MyNamespace;assembly=MyAssembly}Commands'.
And this one in the Command="..." attribute in the binding.
Invalid value for property 'Command': 'Microsoft.VisualStudio.DesignTools.Xaml.LanguageService.Semantics.XmlValue'
UPDATE
Mathew got rid of the errors, however, the menu items with those commands are still grayed out. Relevant code:
<TreeView ...>
<ContextMenu>
<MenuItem Command="{x:Static local:Commands.Create}"/>
</ContextMenu>
...
</TreeView>
MyControl.xaml.cs
//...
private void CanCreateThing(object sender, CanExecuteRoutedEventArgs e) {
e.CanExecute = true;
}
//...
With Mathew's help, a fix was found:
First, I had to replace all instances of local:Commands.Create with {x:Static local:Commands.Create}. However, the menu items would still be gray.
So in each menu item, I added a CommandTarget referencing the ancestor ContextMenu:
<MenuItem Command="{x:Static local:Commands.CreateTrigger}"
CommandTarget="{Binding PlacementTarget, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}}"/>
And that made the menu items clickable.
I have been working with c# for some time now but surprisingly I have never dealt with context menus before. I have a listView control in my universal windows 8.1 app. Now I am trying to get a context menu to popup for each item in the listView (they are all the same type of object and are added to the list as the user adds entries). I have run into several problems with this and have looked at code examples and they seem to be leading in different directions. Firstly when I right click on an item in the list it does not fire the ListView_RightTapped event.
<ListView x:Name="lstvwHours" HorizontalAlignment="Left" Height="264" Margin="427,77,0,0" VerticalAlignment="Top" Width="357" RightTapped="lstvwHours_RightTapped">
Secondly in Microsoft's context menu code example they say to use the PopupMenu class but in other code I've seen it coded into the XAML.
And lastly After the one context menu button is clicked I want it to fire a delete method.
private async void lstvwHours_RightTapped(object sender,
RightTappedRoutedEventArgs e)
{
var menu = new PopupMenu();
menu.Commands.Add(new UICommand("Delete"/*do I put the method to call here?*/));
var chosenCommand = await menu.ShowForSelectionAsync(GetElementRect((FrameworkElement)sender));
}
Here's an example.
In this case you can wire-up the commands that get invoked from your menuitem onto your view-model.
<ListView>
<ListViewItem Content="One">
<ListViewItem.ContextMenu>
<ContextMenu>
<MenuItem Header="Insert"
Command="{Binding DataContext.InsertQuery, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}}"/>
<MenuItem Header="Delete"
Command="{Binding DataContext.DeleteQuery, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}}"/>
</ContextMenu>
</ListViewItem.ContextMenu>
</ListViewItem>
</ListView>
I have a WPF application with Caliburn Micro. On my DataGrid, I have a context menu with two items, which represent two options two select from. How can I add a check mark on the items?
Here is my code:
<DataGrid.ContextMenu>
<ContextMenu >
<MenuItem Header="Treat Invalid Billing Address As Error" cal:Message.Attach="[Event Click] = [Action TreatInvalidBillingAddressAs('Error')]" />
<MenuItem Header="Treat Invalid Billing Address As Warning" cal:Message.Attach="[Event Click] = [Action TreatInvalidBillingAddressAs('Warning')]" />
</ContextMenu>
</DataGrid.ContextMenu>
...
public void TreatInvalidBillingAddressAs(string errorOrWarning)
{
SelectedFirstEntry.BillingAddressValidation = errorOrWarning;
Revalidate();
}
Thanks
As mentioned in the comments to control checked status of the MenuItem you could bind MenuItem.IsChecked property to the BillingAddressValidation property of your view model.
Since this is a property of view model against each row and ContextMenu is defiend against whole DataGrid you can use SelectedFirstEntry item.
<MenuItem ... IsChecked="{Binding SelectedFirstEntry.BillingAddressValidation, Converter={StaticResource ErrorToBoolConverter}}"/>
I want to know if I could assign item click event to this context menu that it is placed in an .Xaml file of type ResourceDictionary which one does not have code behind class, however i know that i can manually assign a .cs class to this .xaml.
But I dont want to assign a file class to it because I already have another .Xaml file with its own .cs file class in which i would want to register the itemClick event.
My code in the resourcedictionary file is:
<ContextMenu>
<MenuItem Header="Show SoundRecorder" Click="ItemClick"></MenuItem>
<Separator/>
<MenuItem Header="Start Recording Now"></MenuItem>
<MenuItem Header="Stop Recording"></MenuItem>
<Separator/>
<MenuItem Header="About"></MenuItem>
<MenuItem Header="Exit SoundRecorder"></MenuItem>
</ContextMenu>
How could i achieve this approach?
Create a command in a data context for the view with the context menu.
public ICommand ItemClickCommand{ get; set; }
Then, you can bind the MenuItem's Command property to the new command.
<ContextMenu>
<MenuItem Header="Show SoundRecorder" Command="{Binding ItemClickCommand}"></MenuItem>
<Separator/>
<MenuItem Header="Start Recording Now"></MenuItem>
<MenuItem Header="Stop Recording"></MenuItem>
<Separator/>
<MenuItem Header="About"></MenuItem>
<MenuItem Header="Exit SoundRecorder"></MenuItem>
</ContextMenu>
At runtime, if WPF finds the command in the data context it will bind the menu item to it. Otherwise, it will issue a warning in the Output console.
I will not go here on implementing the ICommand interface. There are plenty of googlable implementations.