I'm unable to get the keyboard shortcuts working on context menu items belonging to specific controls and I was wondering if anyone could help me.
Use case: I'm trying to write an attached behavior that can be applied to various elements in order to provide undo/redo context menu functionalists to those controls. The context menu part is working but the key bindings don't seem to work.
What I've tried so far:
Attempt 1:
var menu = new ContextMenu();
var undoCommand = new DelegateCommand(Undo);
var undoMenuItem = new MenuItem
{
Header = "Undo",
Command = undoCommand,
InputGestureText = "Ctrl+Z",
};
menu.Items.Add(undoMenuItem);
AssociatedObject.ContextMenu = menu; // AssociatedObject is a textbox as an example
Attempt 2:
var menu = new ContextMenu();
var undoCommand = new DelegateCommand(Undo);
var undoMenuItem = new MenuItem
{
Header = "Undo",
Command = undoCommand,
};
undoMenuItem.InputBindings.Add(new InputBinding(undoCommand,
new KeyGesture(Key.Z, ModifierKeys.Control)))
menu.Items.Add(undoMenuItem);
AssociatedObject.ContextMenu = menu; // AssociatedObject is a textbox as an example
Neither of these seem to be working. The context menu is selectible from the UI (right click on a text box for instance and select "Undo") but the keyboard shortcut is not fired.
Is there a way to do this in an attached behavior? I would like to avoid having access to the underlying Window element inside my attached behavior if possible and would like the keys to work within their respective bounds (for instance, only if the text box is focused should Ctrl+Z cause an Undo on that text box).
Many thanks
Related
I have a context menu for notifyIcon, in which for one of the menu items I want to provide a submenu with three options that can be checked/unchecked. But I want this submenu to appear only when the user hovers/clicks over the arrow in the parent menu item. I.e., the user should be able to select the parent menu item without having to open its submenu, and the default values of the options in the submenu will be used in the parent menu's handler. Is this possible?
I am using Winforms with .Net framework 4.8.1 -
MenuItem[] submenu = new MenuItem[]
{
new MenuItem("Italic",OpenItalic){ DefaultItem = true},
new MenuItem("Bold",OpenBold),
new MenuItem("Underline", OpenUnderline)
};
MenuItem[] menuItems = {
new MenuItem("Show text", submenu)
};
icon = new NotifyIcon()
{
ContextMenu = new ContextMenu(menuItems),
Icon = new System.Drawing.Icon("instance.ico"),
Visible = true,
Text = "test"
};
Here user has to select from the submenu items bold/italic/underline each time to open a form. Can we keep 'italic' as default option and allow the user to open the form by clicking 'Show text' option itself, and only open the submenu when there is a need to change the option?
I need to show a menu on an NSTableView when user right clicks anywhere on the table row. Just like when we right click anywhere in the browser and menu shows up.
NSTableView has Menu property that can be assigned to your NSMenu.
Of course all this can be done in Xcode's IB, but if you are doing this programmatically you need to construct a NSMenu, add the NSMenuItem(s) required and assign it to the NSTableView.
var menu = new NSMenu("A context menu")
{
Delegate = this
};
menu.AddItem(new NSMenuItem { Title = "StackOverflow" Action = SomeMenuAction });
aTableView.Menu = menu;
I've been reading posts for most of the day and can't find this or figure it out. Pretty much all the questions and answers build the menu in XAML but I'm trying do this in code.
The menu builds fine (there's more to it, just abbreviated here) and enables or disables properly but I can't get the command to execute. There is a button on the menu ribbon that resubmits fine so I know the code on the back end works I just can't seem to figure out how to invoke it from the menu. Any ideas would be nice.
Mouse event to build and display menu from MainView.xaml.cs. There are **'s on the line that needs fixed.
private void MainDataGrid_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
ContextMenu m = new ContextMenu();
MenuItem mi = new MenuItem();
m.Items.Add(new MenuItem());
mi = (MenuItem)m.Items[0];
mi.Header = "Resubmit";
**mi.CommandBindings.Add(new CommandBinding(ApplicationCommands.New, ResubmitCommand));**
mi.IsEnabled = MainViewModel.CurrentSelectedItems.Count > 0;
.
.
.
m.IsOpen = true;
}
The ResubmitCommand from my MainViewModel.cs:
public ICommand ResubmitCommand
{
get
{
return _resubmitCommand ??
(_resubmitCommand = new RelayCommand(
o => Resubmit(),
o => CanResubmit));
}
}
Thanks.
You can just set the menu item's Command property:
mi.Command = ResubmitCommand;
By default, ApplicationCommands.New only supports the Ctrl+N input gesture and is usually bound to the main window. You can bind it to a left-click on the menu item:
mi.CommandBindings.Add(new CommandBinding(ApplicationCommands.New,Resubmit));
var leftClickGesture= new MouseGesture(MouseAction.LeftClick);
mi.InputBindings.Add(new InputBinding(ApplicationCommands.New, leftClickGesture));
The lines:
m.Items.Add(new MenuItem());
mi = (MenuItem)m.Items[0];
should be changed to just:
m.Items.Add(mi);
I generate and set my own context menus and group the items into submenus as per
SubTitle.Items.Add(..);
These popup submenus work fine, almost all is nice .. but...
I cannot get the submenu triangle to show up UNLESS i set the MenuItem Role (which you can set per Trigger in Style) to e.g. TopLevelHeader etc.
MenuItem.Role has no direct setter, so i would be obliged to create my submenu MenuItems as XAML static objects that i then endow with nice styles and so they'd get the submenu triangles, too.
The problem is, my context menus are fully programatically derived from e.g. a DB and if I reuse static XAML MenuItems i need set Garbage Collector onto them to break Parent relationship before i can reuse them, and/or i have to know no of these elements in advance.
Is there some way to:
MenuItemThatIsTitle.Role = MenuItemRole.TopLevelHeader;
//(in order to get the triangle?)
..from the code?
===
example code - adding a submenu to context menu from code:
contextM.Items.Add(new Separator());
var TitleH = new MenuItem
{
Header = SettingsDomain.Default.TitleHeader,
FontWeight = FontWeights.Bold,
Height = 25,
IsEnabled = true,
};
if (!(TitleH.Items.Count > 0))
//TitleH.Role = MenuItemRole.TopLevelHeader; to get the triangle..
{
var listmen = List.Select(c => cMenuItem(c)).ToList();
TitleH.ItemsSource = listmen;
}
contextM.Items.Add(TitleH);
contextM.Items.Add(new Separator());
NB: no relevant XAML
Solution: do not set the width of menu to some neat width, it will cut off the right hand side of the menu TOGETHER WITH the submenu marks (triangles) that will simply disappear.
I have a form done in WPF which has a custom control already on it called RateView. This custom control has 4 textboxes (which are all working as they should be). It also contains a button.
I have a second custom control called Extended Margin Info, which also has a XAML Form which will just show output data only.
How can I by clicking the button on the custom control called Rateview bring up the XAML canvas onto my Main window of the extendedmargin info XAML, in the same position everytime? Rateview control exists 5 times on the main window therfore there will be 5 buttons that when clicked, will need to output the popup of ExtendedMargin Info to the main screen in the same position each time with the content of extendedmargin info.
Your button, when clicked, should call a Command which updates a Property of some ViewModel that exposes the ViewModel of the current ExtendedMarginInfo you want to display. Then you can bind this property to the Content Property of a ContentControl in the target view. You can select the View you want the Control to display by using the ContentControl.ContentTemplateSelector property.
I guess you want show one popup and change it's content placing in it different controls.
At 1st create your custom control:
balloon = new LogEntryInfoBalloon();
balloon.SetMainWindow(this);
balloon.DataContext = vm.NotificationViewModel;
Then create Popup control (System.Windows.Controls.Primitives):
localPop = new Popup();
localPop.AllowsTransparency = true;
localPop.Placement = PlacementMode.AbsolutePoint;
localPop.StaysOpen = true;
localPop.PlacementTarget = this;
localPop.Child = balloon;
Placement target points to MainWindow.
Define timer that will close(hide) balloon:
localPopTimer = new Timer(new TimerCallback(CloseLocalPopup));
Close func:
private void CloseLocalPopup(object args)
{
var act = new Action(() =>
{
localPop.IsOpen = false;
});
Dispatcher.BeginInvoke(act, null);
}
Show balloon code looks like this:
private void ShowNotifyBaloon(NotifyBaloonViewModel vm)
{
var act = new Action(() =>
{
localPop.IsOpen = true;
localPopTimer.Change(4000, Timeout.Infinite);
});
Dispatcher.BeginInvoke(act, null);
}