Why won't C# WPF RoutedCommands compile? [duplicate] - c#

This question already has an answer here:
CommandConverter cannot convert from System.String in WPF
(1 answer)
Closed 8 years ago.
<Window x:Class="CostelloM_Data_Persistence_v1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ContactMyPeeps(IllegalVersion)" Height="350" Width="525">
<Window.Resources>
<RoutedCommand x:Key="Saveas"/>
</Window.Resources>
<Window.CommandBindings>
<CommandBinding Command="Saveas" Executed="Save_As"/>
</Window.CommandBindings>
<Window.InputBindings>
<KeyBinding Key="S"
Modifiers="Control + Shift"
Command="Saveas"/>
</Window.InputBindings>
<Grid>
<StackPanel Orientation="Vertical">
<Menu>
<MenuItem Header="File">
<MenuItem Command="Save" Header="Save"/>
<MenuItem Command="Saveas" Header="Save as" InputGestureText="Ctrl+Shift+S"/>
<MenuItem Command="Open" Header="Open"/>
</MenuItem>
</Menu>
<ItemsControl>
<ComboBox>
</ComboBox>
</ItemsControl>
</StackPanel>
</Grid>
</Window>
My problem is as follows, the above code will not compile. I have tried saving, cleaning, and rebuilding my visual studio project and still no dice. It says that command converter cannot convert from system.string. Clearly I either misunderstand RoutedCommand and can not use in this way as a custom command. Is there either a way to force RoutedCommand to create a new command, or a different way to use a custom command?

You are defining a command in a resource so you need to tell the binding system that it is in a resource. You need to change several places in the XAML to this
Command="{StaticResource Saveas}"
However, there are several standard commands pre-defined for you in the ApplicationCommands class like Open, Save, and SaveAs. The binding system will automatically try to bind to these but casing is important. This:
Command="SaveAs"
will bind to the appropriate command defined in ApplicationCommands. Then the command defined in the resources becomes unnecessary.

You've got typos on several lines, which is most likely giving you a "CommandConverter cannot convert from System.String" error because it doesn't recognize the command.
Change this:
<CommandBinding Command="Saveas" Executed="Save_As"/>
To this: (uppercase "A")
<CommandBinding Command="SaveAs" Executed="Save_As"/>

Related

WPF sub menuitem do not show up in the XAML Editor

I created a Menu and inserted a MenuItem. For this MenuItem, I created 3 sub MenuItems.
When I select a sub MenuItem, it does not show up in the XAML editor.
<Window x:Class="CharakterTool3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:CharakterTool3"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<StackPanel>
<Menu>
<MenuItem Header="File">
<MenuItem Header="Open"/>
<MenuItem Header="Close"/>
<MenuItem Header="Exit"/>
</MenuItem>
</Menu>
</StackPanel>
</Window>
This is what I expected:
In my Editor, it do not show up:
During the runtime, it is selectable:
I installed Microsoft Visual Studio Community 2019 Version 16.9.3
with Microsoft .NET Framework Version 4.8.04084.
What is the source of the problem?
This question already has answers here:
How do I open a WPF menu at design-time?
You can set IsSubmenuOpen="True", but if you click somewhere else, menu will close. Set it again to open.

WPF ItemsPanel with Caliburn.Micro MVVM

I'm developing a WPF application and using Caliburn.Micro for MVVM. I'need to dynamically add buttons into view during the runtime.
I have done some research and I got to know that I can achieve this using an ItemControl.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<ItemsControl>
<Button x:Name="ExecuteMethod1" Content="Execute1" />
<Button x:Name="ExecuteMethod2" Content="Execute2" />
<Button x:Name="ExecuteMethod3" Content="Execute3" />
</ItemsControl>
</Grid>
</Window>
Caliburn.Micro's convention allows to call a method which matches to Button's x:Name property. In above code button named ExecuteMethod1 will call a method ExecuteMethod1() in ViewModel.
Problem:
As I'm adding buttons dynamically how can I set the X:Name property for buttons?
I tried to set it using Binding, but WPF doesn't allow to bind X:Name property.
Is there any alternatives? Could anyone can help me with a suggestion?
I am not sure if this a new feature. Got it working from the Caliburn Micro Documentation.
Add Windows Interactivity Assembly. You can pass to your action the Name or the Content of the Button that shall be enough to identify which button was clicked and perform the right action.
CaliburnMicro Actions
<UserControl x:Class="Caliburn.Micro.HelloParameters.ShellView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:cal="http://www.caliburnproject.org">
<StackPanel>
<TextBox x:Name="Name" />
<Button Content="Click Me">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<cal:ActionMessage MethodName="SayHello">
<cal:Parameter Value="{Binding ElementName=Name, Path=Text}" />
</cal:ActionMessage>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</StackPanel>
</UserControl>

MenuItem in Window, CommandBinding in UserControl

I have a window:
<Window x:Class="SomeNamespace.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="350" Width="525">
<Window.CommandBindings>
<CommandBinding Command="ApplicationCommands.Copy"
CanExecute="CommandCanExecute" Executed="CommandExecuted"/>
</Window.CommandBindings>
<DockPanel>
<Menu DockPanel.Dock="Top">
<MenuItem Header="File">
<MenuItem Command="ApplicationCommands.Copy"/>
</MenuItem>
</Menu>
</DockPanel>
</Window>
With some code behind:
void CommandCanExecute(object sender, CanExecuteRoutedEventArgs e) {
e.CanExecute = true;
}
void CommandExecuted(object sender, EventArgs e) {
MessageBox.Show("Done!");
}
And everything works the way I expect. I can use the MenuItem or the Ctrl+C input binding to run my command.
But now my class has gotten too big, and I decide to refactor. So I moved my code behind to a user control. Here's my new Window:
<Window x:Class="SomeNamespace.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:SomeNamespace"
Height="350" Width="525">
<DockPanel>
<Menu DockPanel.Dock="Top">
<MenuItem Header="File">
<MenuItem Command="ApplicationCommands.Copy"/>
</MenuItem>
</Menu>
<my:UserControl1/>
</DockPanel>
</Window>
And my UserControl:
<UserControl x:Class="ImageDecompileSandbox.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<UserControl.CommandBindings>
<CommandBinding Command="ApplicationCommands.Copy"
CanExecute="CommandCanExecute" Executed="CommandExecuted"/>
</UserControl.CommandBindings>
</UserControl>
Basically, everything is the same, except the CommandBinding was moved from the window to UserControl and the two command methods were pushed down to the user control.
Question: Why does the above not work? Why is my User Control's command not picked up by the window? How do I get the MenuItem / KeyBindings from the window to work with the command execution in the User Control?
Thanks to dkozl, I was able to find a way to make this work.
The trick was indeed adding the CommandBinding back to the Window. Instead of declaring them all in the Window, which I can't do as the window doesn't know about the methods being used for Executed and CanExecute, I just added all the bindings from the control to the window:
CommandBindings.AddRange(_userControl1.CommandBindings);
I find this one-line hack to be exactly what I need, as it lets me keep the command controls and keybindings in the window while moving the command implementation to the control.
Thanks for the help dkozl!

Add Short Cut Key to button [duplicate]

This question already has answers here:
Keyboard shortcuts in WPF
(11 answers)
Closed 9 years ago.
How Can I Add Short Cut Key To button in wpf?
I have three window with New Button and i want to add Ctrl+N or etc short cut to all of them.
you can do it as following method too. in form write method indicating short cut keys.
private void shortcutKey_Click(object sender, System.Windows.Input.KeyEventArgs e)
{
if ((e.Key == Key.N) && (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)))
ProjMnuBtn_AddProj_Click(null, null);
}
then in xaml file you need to set it as follows:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="1280" Height="920" KeyUp="shortcutKey_Click">
</Window>
Here is a great tutorial for this : https://web.archive.org/web/20150430045153/http://tech.pro:80/tutorial/839/wpf-tutorial-command-bindings-and-custom-commands
Sample (taken from link above)
<Window x:Class="CustomCommandTest.CommandWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Custom Command Test" Height="300" Width="300">
<Window.CommandBindings>
<CommandBinding Command="Help"
CanExecute="HelpCanExecute"
Executed="HelpExecuted" />
</Window.CommandBindings>
<Window.InputBindings>
<KeyBinding Command="Help" Key="H" Modifiers="Ctrl"/>
<MouseBinding Command="Help" MouseAction="LeftDoubleClick" />
</Window.InputBindings>
<StackPanel>
<Button Command="Help" Content="Help Command Button" />
<Button Content="My Command" x:Name="MyCommandButton" />
</StackPanel>
</Window>

How to bind a dependency property to a window resource in WPF?

Suppose I have a context menu as a window resource:
<Window.Resources>
<ContextMenu
x:Shared="false"
x:Key="ContextMenu">
<MenuItem Header="{??}" />
</ContextMenu>
</Window.Resources>
And I want to bind MenuItem.Header to a dependency property called MenuItemHeader on the window. What should {??} be and what should the code behind in the window class look like?
You could name the window and reference it
<Window Name="Window" ...>
<MenuItem Header="{Binding MyDp, Source={x:Reference Window}}"...>
MyDp being the property. If you don't know how to define a dependency property read the overview.
(I would use Source and x:Reference as ElementName usually does not work in disconnected places like ContextMenus)

Categories

Resources