WPF CommandBinding not working - wpf

I have a button in WPF window. I want to display a message by both pressing left mouseclick and by clicking Ctrl+F. I want most of the code in XAML. Code is as given below.
My problem is that mouse click is working for me but not the key press. Can anybody please help me. Thanks in advance.
MyWindow.xaml
<Window x:Class="Commands_Xaml.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="164,88,0,0" Name="button1" VerticalAlignment="Top" Width="75">
<Button.CommandBindings>
<CommandBinding Command="ApplicationCommands.Find" Executed="CommandBinding_Executed"/>
</Button.CommandBindings>
<Button.InputBindings>
<KeyBinding Key="F" Modifiers="Control" Command="ApplicationCommands.Find"/>
<MouseBinding MouseAction="LeftClick" Command="ApplicationCommands.Find"/>
</Button.InputBindings>
</Button>
</Grid>
</Window>
MainWindow.xaml.cs
namespace Commands_Xaml
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
//ApplicationCommands.Find.InputGestures.Add(new KeyGesture(Key.F,ModifierKeys.Control));
//ApplicationCommands.Find.InputGestures.Add(new MouseGesture(MouseAction.LeftClick));
//CommandBinding bindingObject = new CommandBinding();
//bindingObject.Command = ApplicationCommands.Find;
//bindingObject.Executed += new ExecutedRoutedEventHandler(CommandBinding_Executed);
//this.CommandBindings.Add(bindingObject);
}
private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
{
MessageBox.Show("Button clicked");
}
}
}

Move the command binding / input binding to the window level and use the Command property of the button instead of trying to use a MouseBinding.
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.CommandBindings>
<CommandBinding Command="ApplicationCommands.Find" Executed="CommandBinding_Executed" />
</Window.CommandBindings>
<Window.InputBindings>
<KeyBinding Command="ApplicationCommands.Find" Key="F" Modifiers="Control" />
</Window.InputBindings>
<Grid>
<Button Command="ApplicationCommands.Find" Content="Button" HorizontalAlignment="Left" Margin="206,152,0,0" VerticalAlignment="Top" Width="75"/>
</Grid>
</Window>
UPDATE
To have different behavior based on different button clicks, this can be accomplished a few ways. Here are two:
Use a different command for each button:
<Button Command="ApplicationCommands.Find" Content="Button1" />
<Button Command="ApplicationCommands.Print" Content="Button2" />
Use CommandParameter:
<Button Command="ApplicationCommands.Find" CommandParameter="Find1" Content="Button1" />
<Button Command="ApplicationCommands.Find" CommandParameter="Find2" Content="Button2" />
And for the KeyBinding:
<KeyBinding Command="ApplicationCommands.Find" CommandParameter="Find3" />
You can access this property in the CommandBinding.Executed handler:
private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
{
if (e.Parameter as string == "Find1")
{
//Find1
}
else if (e.Parameter as string == "Find2")
{
//Find2
}
else if (e.Parameter as string == "Find3")
{
//Find3
}
}

Related

Invoking a WPF view (UserControl) method from the main window (Window)

I have a button on a view (UserControl) that invokes a method in the code-behind file. I would like to get rid of the button and instead, invoke the method from a menu item. Not sure how to do this. Here is some simple code illustrating this situation:
MainWindow.xaml (MainView is embedded):
<Window x:Class="Example.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:View="clr-namespace:Example.View"
Title="MainWindow" Height="600" Width="800" Background="Green">
<Grid>
<StackPanel>
<Menu>
<MenuItem Header="File" Click="MenuItem_Click">
</MenuItem>
</Menu>
<View:MainView/>
</StackPanel>
</Grid>
MainWindow.xaml.cs
using System.Windows;
namespace Example
{
public partial class MainWindow : Window
{
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("MainWindow");
// how can I invoke MainView methods like DoWork from here?
}
}
}
MainView.xaml
<UserControl x:Class="Example.View.MainView"
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"
mc:Ignorable="d" d:DesignHeight="500" d:DesignWidth="600">
<Grid Background="Yellow">
<Button HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10" Content="Show" Click="Button_Click"/>
</Grid>
</UserControl>
MainView.xaml.cs
using System.Windows.Controls;
namespace Example.View
{
public partial class MainView : UserControl
{
public MainView()
{
InitializeComponent();
}
private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
{
DoWork();
}
public void DoWork()
{
MessageBox.Show("MainView");
}
}
}
You could just give a name to the MainView,
<Window x:Class="Example.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:View="clr-namespace:Example.View"
Title="MainWindow" Height="600" Width="800" Background="Green">
<Grid>
<StackPanel>
<Menu>
<MenuItem Header="File" Click="MenuItem_Click"/>
</Menu>
<View:MainView x:Name="mainView"/>
</StackPanel>
</Grid>
</Window>
and call the Method like this:
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
mainView.DoWork();
}

wpf how to change a canvas image Position programmatically

I am a student on my final year and im doing a project regarding WPF but i'm totally new to WPF and i have been assigned some tasks,but im currently stuck on how to change the Image position on the canvas programitically from left to right.below are the codes
<<Window x:Class="changing_bird_position.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="450" Width="800">
<StackPanel>
<Canvas Name="canvas" Background="LightBlue" Width="500" Height="280" Margin="264,0,28,0">
<Image Source="inlandbird.png" Name="Image" Height="43" Canvas.Left="55" Canvas.Top="22"/>
</Canvas>
<Button Content="Button" Click="Button_Click" Width="50" Height="50" Margin="246,0"/>
</StackPanel>
Xaml.cs
public partial class MainWindow : Window
{
Image img = new Image();
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Canvas.SetLeft(img, 200.0);
Canvas.SetTop(img, 200.0);
In your code behind you don't need to create this instance of an Image (img). You can access the image by it's name property.
I renamed the image in the xaml to make it clear.
XAML:
<Window x:Class="WpfApplication15.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="450" Width="800">
<StackPanel>
<Canvas Name="canvas" Background="LightBlue" Width="500" Height="280" Margin="264,0,28,0">
<Image Source="inlandbird.png" Name="BirdImage" Height="43" Canvas.Left="55" Canvas.Top="22"/>
</Canvas>
<Button Content="Button" Click="Button_Click" Width="50" Height="50" Margin="246,0"/>
</StackPanel>
</Window>
Code behind:
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Canvas.SetLeft(BirdImage, 200.0);
Canvas.SetTop(BirdImage, 200.0);
}
}
}

How to create hotkey for button by modifying xaml?

I am trying to learn keybinding in WPF by a simple example.
here is my XAML file:
<Window.Resources>
<RoutedUICommand x:Key="myNewCommand"></RoutedUICommand>
</Window.Resources>
<Window.CommandBindings>
<CommandBinding Command="{StaticResource myNewCommand}" Executed="Button_Click"></CommandBinding>
</Window.CommandBindings>
<Window.InputBindings>
<KeyBinding Command="{Binding myNewCommand}" Key="B" />
</Window.InputBindings>
<Grid>
<Button Command="{Binding myNewCommand}" Click="Button_Click" Content="Click Here"/>
</Grid>
And this is code behind for Button_Click :
private void Button_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("hello");
}
I get the "hello" message when I click on button, but no response when I press "B" on keyboard.
I want to have this binding without changing the Button_click, can I do it just in XAML? how?
Your command bindings aren't correct. You should replace {Binding myNewCommand} with {Binding Source={StaticResource myNewCommand}}. It is also not necessary to have a Click handler on the button when you have already bound a command.
<Window.Resources>
<RoutedUICommand x:Key="myNewCommand"/>
</Window.Resources>
<Window.CommandBindings>
<CommandBinding Command="{StaticResource myNewCommand}"
Executed="MyCommandExecuted"/>
</Window.CommandBindings>
<Window.InputBindings>
<KeyBinding Command="{Binding Source={StaticResource myNewCommand}}" Key="B" />
</Window.InputBindings>
<Grid>
<Button Command="{Binding Source={StaticResource myNewCommand}}"
Content="Click Here"/>
</Grid>
The Executed handler:
private void MyCommandExecuted(object sender, RoutedEventArgs e)
{
MessageBox.Show("hello");
}

Binding to a property of a borders child

I have implemented my own simple version of a navigation window, mainly because navigation windows journal does not give me control over how many children can exist. So I am using a border inside a window and changig its child everytime. As children I am using a UserControl. I want to bind the title of my Window to the Title property of my current child. Somehow I cannot figure out a way to do it.
MainWindow XAML:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="525"
Height="350"
Background="AliceBlue"
Title="{Binding Path=Child.Title,
ElementName=borderContent}">
<DockPanel>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<Button Content="<-" x:Name="btnBack" />
<Button Content="->" x:Name="btnForward" />
</StackPanel>
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
<Button Content="1" Click="Button_Click_1" />
<Button Content="2" Click="Button_Click_2" />
</StackPanel>
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Border x:Name="borderContent" />
</ScrollViewer>
</DockPanel>
MainWindow Code behind:
using System;
using System.Windows;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
this.borderContent.Child = new ContentPage("Title 1");
}
private void Button_Click_2(object sender, RoutedEventArgs e)
{
this.borderContent.Child = new ContentPage("TITLE 2");
}
}
}
UserControl XAML:
<UserControl x:Class="WpfApplication1.ContentPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<TextBlock Text="{Binding Source={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=Title}" />
</Grid>
User Control Code behind:
using System.Windows;
using System.Windows.Controls;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for Content.xaml
/// </summary>
public partial class ContentPage : UserControl
{
public string Title
{
get { return (string)this.GetValue(ContentPage.TitleProperty); }
set { this.SetValue(ContentPage.TitleProperty, value); }
}
// Using a DependencyProperty as the backing store for Title. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TitleProperty =
DependencyProperty.Register("Title", typeof(string), typeof(ContentPage), new UIPropertyMetadata(string.Empty));
public ContentPage(string Title)
{
this.Title = Title;
InitializeComponent();
}
}
}
Somehow the binding inside the UserControl is also not working. What am I doing wrong?
The problem is that the Child property of a Borderisn't a DependencyProperty so there is no change notification. You'll have to update the Binding manually everytime you change the Child
private void Button_Click_1(object sender, RoutedEventArgs e)
{
this.borderContent.Child = new ContentPage("Title 1");
UpdateTitleBindingExpression();
}
private void Button_Click_2(object sender, RoutedEventArgs e)
{
this.borderContent.Child = new ContentPage("TITLE 2");
UpdateTitleBindingExpression();
}
private void UpdateTitleBindingExpression()
{
BindingExpressionBase beb = BindingOperations.GetBindingExpressionBase(this, Window.TitleProperty);
if (beb != null)
{
beb.UpdateTarget();
}
}
I'm not sure why you are doing what you are doing, but regarding your question:
change "Source" to "RelativeSource"
<Grid>
<TextBlock Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=Title}" />
</Grid>
That should fix the binding issue
Edit:
When you really want to do it that way, you could make the borderContent element an ContentControl and use the Content property instead. Since this is an DependencyProperty you're binding will work:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="525"
Height="350"
Background="AliceBlue"
Title="{Binding Content.Title, ElementName=borderContent}">
<DockPanel>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<Button Content="<-" x:Name="btnBack" />
<Button Content="->" x:Name="btnForward" />
</StackPanel>
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
<Button Content="1" Click="Button_Click_1" />
<Button Content="2" Click="Button_Click_2" />
</StackPanel>
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<ContentControl x:Name="borderContent" />
</ScrollViewer>
</DockPanel>
</Window>

How can I databind a non-command MenuItem IsEnabled to stay consistent with a command based MenuItem?

This menuItem because it's linked to a command does the magic behind the scenes for me:
<MenuItem Name="mnuOpen" Command="Open"/>
where I have
<Window.CommandBindings>
<CommandBinding Command="Open"
Executed="CommandBinding_Open_Executed"
CanExecute="CommandBinding_ProjectSelected"/>
</Window.CommandBindings>
but every binding I've tried has failed to do anything.
<MenuItem Name="mnuExplorer" Click="mnuExplorer_Click" Header="Open Containing Folder" IsEnabled="{Binding ElementName=mnuOpen, Path=IsEnabled}" />
It works fine maybe you forgot to set CanExecute flag or have other dependency
full code
<Window x:Class="MenuBinding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.CommandBindings>
<CommandBinding Command="Open"
Executed="CommandBinding_Executed"
CanExecute="CommandBinding_CanExecute"/>
</Window.CommandBindings>
<Grid>
<Menu>
<MenuItem Name="mnuOpen" Command="Open" IsEnabled="False" />
<MenuItem Name="mnuExplorer" Header="Open Containing Folder" IsEnabled="{Binding ElementName=mnuOpen, Path=IsEnabled}" />
</Menu>
</Grid>
and class
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
{
MessageBox.Show("Magic");
}
private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true; //define if command can be executed
}
}

Resources