I checked a lot of of answers here about shortcuts bindings, but did not find the simple way to execute some method from the C# code.
First, in the following classic example I don't understand what actually we are binding. What the meaning of Command attribute? What is the ApplicationCommands? Where is ApplicationCommands.Open has been declared?
<Window.InputBindings>
<KeyBinding Command="ApplicationCommands.Open"
Gesture="CTRL+R" />
</Window.InputBindings>
In the one of answer of question similar to my one, "XAML is the markup language, so we could not call the method from there" has been told. OK, in this case, WHY we can call the method OnClickBtn1 from the code below?
<Button
x:Name="SomeButton"
Click="OnClickBtn1"/>
Finally, my problem. All I need is to execute OnClickBtn1 method by Ctrl+H (for example) shortcut same as effect when the button Btn1 clicked. I understand that following code is not enough.
XAML:
<Window x:Name="MainDisplay"
<!-- ... --->
>
<Window.InputBindings>
<KeyBinding Gesture="Ctrl+H" Command="{Binding OnClickBtn1}" />
</Window.InputBindings>
<!-- ... -->
<Button x:Name="Btn1"
Width="70"
Content="Button"
Click="OnClickBtn1"/>
C#:
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
}
private void OnClickBtn1(object sender, RoutedEventArgs e) {
System.Diagnostics.Debug.WriteLine("Btn1 has been clicked or Ctrl+H had been inputed");
}
}
Related
I have a wpf application with a MVVM. I am trying here to build my own close button. Based on this answer Creating a custom Close Button in WPF I added a button event handler in the View(xaml.cs) code. However, it is not recognizing the Close(); call (doesn't exist in the context - Can't resolve symbol).
Also I tried the other answer and added Command and CommandParameter into my button's xaml. But the function behind is not getting hits. In How to bind Close command to a button using the RelayCommand also my wpf is not recognizing RelayCommand. Then How can I use the RelayCommand in wpf said that I have to write it myself(really?). I remember there was a simple way similar to just set an event handler for the button and call Close();. But, how can I do that or why it is not working for me?
View code:
private void closeButton_Click(object sender, RoutedEventArgs e)
{
// I want to call close the whole app on button click
//Close(); is not recognized
}
private void performMainCloseButtonCommand(object Parameter)
{
// This doesn't get hits on button click
Window objWindow = Parameter as Window;
objWindow.Close();
}
Button XAML:
<Button x:Name="closeButton" RenderTransformOrigin="0.5,0.5" Padding="0" Margin="701,0,0,0" BorderThickness="0" Click="closeButton_Click" Command="{Binding MainCloseButtonCommand}" CommandParameter="{Binding ElementName = mainWindow}" Height="45" Width="45" >
<StackPanel Height="45" Width="45">
<Image x:Name="closeButtonImage" Margin="0" Source="/ProjectName;component/Resources/x.fw.png" Height="33"/>
<TextBlock Text="Close" Width="36" Padding="6,0,0,0" HorizontalAlignment="Center" Height="13" FontSize="10"/>
</StackPanel>
</Button>
Close isn't recognized in your event handler because there is probably no method called Close in your current class. If you want to call main window's close method you can use:
private void closeButton_Click(object sender, RoutedEventArgs e)
{
Application.Current.MainWindow.Close();
}
Above is not a good way to do this and does not align with MVVM pattern. Which relates to your second question. Without seeing remaining part of your code, its hard to say why command binding isn't working. My guess you haven't wired up the commands properly for it to fire. You will need to ensure that you have created your RelayCommand instance and your command properties are correctly set.
I'm new to WPF and I'm trying to dynamically add a Button inside a ContentControl, which should fire a command when clicked. I'm using MVVMLight to handle the Commands.
Below I have an example with two buttons. The top button is placed directly into the StackPanel. This button fires off the Command as expected.
The second button is placed inside a ContentControl. It displays correctly, but the Command does not fire when the button is clicked.
I assumed this is because the Binding does not transfer down through the DataTemplate, but it seems to work if I use regular Commands instead of MVVMLight RelayCommands.
I don't want to remove the framework, so I'm wondering if anyone knows how to fix it? Thanks
<Window x:Class="ContentControlExample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:ContentControlExample.ViewModel">
<Window.DataContext>
<vm:MainViewModel />
</Window.DataContext>
<Window.Resources>
<DataTemplate x:Key="MyButton" >
<Button Content="SUBMIT" Command="{Binding MyCommand}" Width="200" Height="50"/>
</DataTemplate>
</Window.Resources>
<StackPanel>
<!--When this button is clicked, the Command executes as expected-->
<Button Content="SUBMIT" Command="{Binding MyCommand}" Width="200" Height="50"/>
<!--Nothing happens when this button is clicked-->
<ContentControl ContentTemplate="{StaticResource MyButton}"/>
</StackPanel>
</Window>
Here's the ViewModel with the command:
public class MainViewModel : ViewModelBase
{
public ICommand MyCommand { get; private set; }
public MainViewModel()
{
MyCommand = new RelayCommand(MyCommand_Executed, MyCommand_CanExecute);
}
private bool MyCommand_CanExecute()
{
return true;
}
private void MyCommand_Executed()
{
MessageBox.Show("The command executed");
}
}
The problem here is the implicit DataContext in ContentTemplate is the Content and this has not been set to anything. You need to set Content to some Binding to bridge the DataContext currently in the visual tree, something like this:
<ContentControl ContentTemplate="{StaticResource MyButton}" Content="{Binding}"/>
Another solution is to give your Window a name:
<Window x:Class="ContentControlExample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:ContentControlExample.ViewModel"
x:Name="_this">
Then bind via its context instead:
<Button Content="SUBMIT" Command="{Binding ElementName=_this, Path=DataContext.MyCommand}" Width="200" Height="50"/>
This is particularly handy for things like ListViews and ItemControls, as their DCs get set to the list elements. Keep in mind though that this will only work on members within the same visual tree, if that's not the case (e.g. popup menus etc) then you need to proxy a binding as described in this article.
I have a MainWindow.XAML and CustomersView.XAML.
When I click the Customer Button on MainWindow , I want to navigate to CustomersView.XAML and palong with that need to pass few parameters.
I can use NavigationService but is only available with Pages and not Window.Hyperlink is not an option at this moment.
This might be fairly simple thing but not sure how can I implement this using MVVM and with out any third party control.
private void Navigate_Click(object sender, RoutedEventArgs e)//By Prince Jain
{
this.NavigationService.Navigate(new Uri("Page3.xaml", UriKind.Relative));
}
There are many options to navigate from one window to another in WPF. You can use a frame in your MainWindow and navigate all your pages right inside your Frame.
<Window
x:Class="NavigationSample.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<DockPanel>
<Frame x:Name="_mainFrame" />
</DockPanel>
</Window>
From code, you can tell the frame to navigate, like so:
_mainFrame.Navigate(new Page1());
Which just so happens to be a helpful shortcut to:
_mainFrame.NavigationService.Navigate(new Page1());
Or if you using any framework like PRISM, you are allowed to create a Shell where you can define regions and let your pages navigate to that.
Navigation Using the Prism Library 5.0 for WPF
Simple Way in XAML:
<Button HorizontalAlignment="Right" Name="continueButton" Width="75"
Margin="0,0,8,11" Height="23" VerticalAlignment="Bottom"
Click="continueButton_Click">
Navigate
</Button>
C#:
private void continueButton_Click(object sender, RoutedEventArgs e)
{
this.NavigationService.GoForward();
//or
this.NavigationService.Navigate("Second.xaml")
}
In MVVM XAML:
<Button Command="{x:Static Views:Commands.NavigateHelp}"
Content="Help"/>
In Views (We have a Commands.cs file that contains all of these):
public static RoutedCommand NavigateHelp = new RoutedCommand();
In the page constructor, you can connect the two:
CommandBindings.Add(new CommandBinding(Commands.NavigateHelp,
NavigateHelpExecute));
NavigateHelpExecute can be in the code behind (which is what we do), hook into a ViewModel event handler, or whatever. The beauty of this is that you can disable other navigation like so:
CommandBindings.Add(new CommandBinding(NavigationCommands.Refresh, null));
I am working with WPF. I want to create keyboard shortcuts for my WPF application. I have created as following. The first command binding tag for "open" is working and command binding for exit is not working. I dont know what is the reason.
<Window.CommandBindings>
<CommandBinding Command="Open" Executed="CommandBinding_Executed"/>
<CommandBinding Command="Exit" Executed="CommandBinding_Executed_1" />
</Window.CommandBindings>
<Window.InputBindings>
<KeyBinding Command="Open" Key="O" Modifiers="control" />
<KeyBinding Command="Exit" Key="E" Modifiers="control"/>
</Window.InputBindings>
Above code is getting the following error:
Cannot convert string 'Exit' in attribute 'Command' to object of type
'System.Windows.Input.ICommand'. CommandConverter cannot convert from
System.String. Error at object 'System.Windows.Input.CommandBinding' in
markup file 'WpfApplication2;component/window1.xaml' Line 80 Position 25.
You problem is that there is no exit command. You'll have to roll your own.
See here for built-in ApplicationCommands
It's pretty easy to create your own, I use a static utility class to hold common commands that I use often. Something like this:
public static class AppCommands
{
private static RoutedUICommand exitCommand = new RoutedUICommand("Exit","Exit", typeof(AppCommands));
public static RoutedCommand ExitCommand
{
get { return exitCommand; }
}
static AppCommands()
{
CommandBinding exitBinding = new CommandBinding(exitCommand);
CommandManager.RegisterClassCommandBinding(typeof(AppCommands), exitBinding);
}
}
Then you should be able to bind it like this:
<KeyBinding Command="{x:Static local:AppCommands.Exit}" Key="E" Modifiers="control"/>
I use standard Cut, Copy and Paste commands (which is part of ApplicationCommands class). Is it possible to redefine CanExecute method?
Here is my code:
XAML:
<Window.CommandBindings>
<CommandBinding Command="Copy"
CanExecute="CopyCanExecute" Executed="CopyExecuted"/>
</Window.CommandBindings>
<StackPanel>
<TextBox Name="txt"></TextBox>
<Button Command="Copy" CommandTarget="{Binding ElementName=txt}">copy</Button>
</StackPanel>
Code-behind:
private void CopyCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = false;
}
private void CopyExecuted(object sender, ExecutedRoutedEventArgs e)
{
MessageBox.Show("Copy Executed");
}
The button still behave like its command is standard Copy command.
You do this via a CommandBinding. The local CommandBinding can specify a CanExecuteHandler.
For details and a working example, see this blog post.
The copy command will not work when the focus is on a textbox where the commands have already been handled, but it will work on elements like CheckBox etc.
In the CanExecute handler you might need to add `e.Handled = true; also, so that it doesnt go and execute the standard Copy.CanExecute()
You can set the commandbinding to the textbox directly instead of to the window.