Why this simple WPF command does not work? - c#

I'm trying to add a WPF custom command to a control. What I've done:
XAML:
<Window x:Class="H.I.S.windows.CommandTest"
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:H.I.S.windows"
mc:Ignorable="d"
Title="CommandTest" Height="450" Width="800">
<Window.CommandBindings>
<CommandBinding Command="local:CustomCommand.Save" CanExecute ="SaveCommand_CanExecute" Executed="SaveCommand_Executed" />
</Window.CommandBindings>
<Grid>
<Button Command="local:CustomCommand.Save" Height="50" Width="100">Click me!</Button>
</Grid>
</Window>
C#:
namespace H.I.S.windows
{
public partial class CommandTest : Window
{
public CommandTest()
{
InitializeComponent();
}
private void SaveCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
private void SaveCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
MessageBox.Show("Saved");
}
}
public static class CustomCommand
{
public static readonly RoutedUICommand Save = new RoutedUICommand(
"Save",
"Save",
typeof(CustomCommand),
new InputGestureCollection()
{
new KeyGesture(Key.F2)
}
);
}
}
The button is disabled (even in design mode) and doesn't let the user click on it.
I've just implemented codes described HERE.
Where I'm wrong?

The code what you have posted throws me an error because of this below statement,
<Window.CommandBindings>
<CommandBinding Command="local:CustomCommand.Save" CanExecute ="CommandBinding_CanExecute" Executed="CommandBinding_Executed" />
</Window.CommandBindings>
It started working for me after changing it to below,
<Window.CommandBindings>
<CommandBinding Command="local:CustomCommand.Save" CanExecute ="SaveCommand_CanExecute" Executed="SaveCommand_Executed" />
</Window.CommandBindings>
The event handlers in your code-behind are different from what you have in your xaml for CommandBinding.
"SaveCommand_CanExecute" and "SaveCommand_Executed"
After changing as above, it works for me and I can see the messagebox with "Saved" message when I hit click on it.
Hope you are not missing this. If something else stopping you then try to see if it shows any errors on further and let us know.

As #SirRufo suggested in question comments, Problem was that I declared "CommandBindings" for whole WPF window and button inside another control.
There are 2 solutions for this case:
1: Declaring CommandBindings for Button's direct parent.
2: Set name for control which is bound with command and add some code like below to control:
<Window ... x:Name = "windowName" ...>
<Window.CommandBindings>
<CommandBinding Command="custumCommand:CustomCommands.Save" CanExecute ="CommandBinding_CanExecute" Executed="CommandBinding_Executed" />
</Window.CommandBindings>
<Grid>
<StackPanel>
<GroupBox>
<Button Command="custumCommand:CustomCommands.Save" CommandTarget = "{Binding ElementName=windowName}" Content="Save" />
</GroupBox>
</StackPanel>
</Grid>
</Window>
Look at "CommandTarget" attribute of Button.

Related

C# WPF - Popup which doesn't get focused

Im simply trying to make a little popup which shows a message in the corner. This Popup shuld be at the top of every other Window which I achieved with "TopMost", but I can't seem to get the unfocusable thing to work...
My PopUp XAML:
<Window x:Class="message.Popup"
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:message"
mc:Ignorable="d"
Title="Popup" Height="129.808" Width="300" Focusable="False" Topmost="True">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="179*"/>
<ColumnDefinition Width="113*"/>
</Grid.ColumnDefinitions>
<Label x:Name="label" Content="" HorizontalAlignment="Left" Margin="10,40,0,0" VerticalAlignment="Top" Width="272" Grid.ColumnSpan="2"/>
</Grid>
How I call it (from annother Window):
private void textBox_TextChanged(object sender, TextChangedEventArgs e)
{
new Popup(textBox.Text).Show();
}
PopUp code:
public Popup(string text)
{
InitializeComponent();
label.Content = text;
}
you must define your Mainwindow as Owner of the Popup and center the StartupLocation Property. Something like this:
PopUpWindow.Owner = MainWindow;
PopUpWindow.WindowStartupLocation = WindowStartupLocation.CenterOwner;
Or if you are calling it from another window:
PopUpWindow.Owner = this;
PopUpWindow.WindowStartupLocation = WindowStartupLocation.CenterOwner;
However I must say: this is not MVVM, since you are storing text in the Window class, and I strongly recommend you start reading about MVVM.

How to make a RichTextBox stop consuming key gestures

The RichTextBox provides a lot of commands with accompanying key gestures.
However, when IsReadOnly=True is set, many of those commands do not make sense and do not take any action, e.g. Ctrl+I, Ctrl+R. Nevertheless, when a command in the Window uses one of the key gestures, the command in the Window does not fire when the RichtTextBox has focus:
<Window x:Class="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:"
mc:Ignorable="d">
<Window.CommandBindings>
<CommandBinding Command="local:MainWindow.MyCommand" Executed="MyCommandBinding_Executed" />
</Window.CommandBindings>
<StackPanel>
<RichTextBox Height="50" IsReadOnly="True" />
<CheckBox Content="This is a checkbox" />
<TextBlock Name="whatsGoingOn" />
</StackPanel>
</Window>
using System.Windows;
using System.Windows.Input;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
public static RoutedUICommand MyCommand = new RoutedUICommand(
"My Command",
"MyCommand",
typeof(MainWindow),
new InputGestureCollection() { new KeyGesture(Key.R, ModifierKeys.Control) });
private void MyCommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
{
whatsGoingOn.Text += ".";
}
}
Now maybe the right answer is “don’t use RichTextBox with IsReadOnly="True", use something else instead”, but let’s assume I had to or wanted to use RichTextBox.
What can I do to make key gestures fire my command even when the RichTextBox has focus?
You can intercept the keystrokes in the PreviewKeyDown event of the RichTextBox. Set the e.Handled member to true and that will prevent the actually processing of the keys.
Hope it helps

DependencyPropertyDescriptor help required

I have a simple WPF app, where I have a combobox and a label, using dependency property I want to show the selected Item in label, when user select any item in the combobox, label will be changed accordingly.
Here is my code.
public event EventHandler _itemChanged;
public MainWindow()
{
List<String> items = new List<string>();
items.Add("C");
items.Add("C++");
items.Add("C#");
items.Add("Java");
items.Add("Js");
InitializeComponent();
combx.ItemsSource = items;
_itemChanged += MainWindow__itemChanged;
DependencyPropertyDescriptor dpcombx;
dpcombx =
DependencyPropertyDescriptor.FromProperty((DependencyProperty)
ComboBox.SelectedValueProperty, typeof(ComboBox));
dpcombx.AddValueChanged(dpcombx, _itemChanged);
}
void MainWindow__itemChanged(object sender, EventArgs e)
{
ComboBox cb = (ComboBox) sender;
lbl_Combx.Content = (string)cb.SelectedItem;
}
The problem is, EventHandler is not getting called. Please help me.
here is the XAML
<Window x:Class="DP.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>
<ComboBox Name="combx"
HorizontalAlignment="Left"
Margin="57,121,0,0"
VerticalAlignment="Top"
Width="120" />
<Label Content=""
x:Name="lbl_Combx"
HorizontalAlignment="Left"
Margin="368,182,0,0"
VerticalAlignment="Top" />
</Grid>
</Window>
You need to pass the dependency object (comboBox) in the AddValueChanged instead of its property descriptor.
dpcombx.AddValueChanged(combx, _itemChanged);

How to show programmatically FocusVisualStyle?

Afters attemps I could tell that the FocusVisualStyle is only activated by the keyboard (tab and arrows keys).
Try to make the FocusVisualStyle to be applied after the component is loaded, it is impossible to do, There is an easy way to get around this problem?
I found this:
- focus visual not showing when navigating focus programically
- How do WPF buttons decide to show FocusVisualStyle?
- http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/99856840-f8ef-4547-9150-c4c46ec2f3df
But none shows a definite solution (without overwriting the component), and I could not write, can someone help?
I am not pretty sure I understand your issue, but I tried the example in one of the links and I was able to move focus to next component from code behind exactly as you would do using keyboard. Here is the code.
<Window x:Class="WpfApplication1.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"
xmlns:local="clr-namespace:WpfApplication1" Loaded="OnLoaded"
>
<StackPanel Margin="10">
<TextBox Margin="10" x:Name="a" >A</TextBox>
<TextBox Margin="10" x:Name="b" >B</TextBox>
<Button Focusable="False" Click="OnClick">Move Focus</Button>
</StackPanel>
</Window>
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
}
private void OnLoaded(object sender, RoutedEventArgs e) {
a.Focus();
}
private void OnClick(object sender, RoutedEventArgs e) {
var request = new TraversalRequest(FocusNavigationDirection.Next);
var elementWithFocus = FocusManager.GetFocusedElement(FocusTest) as UIElement;
if (elementWithFocus != null)
elementWithFocus.MoveFocus(request);
}
}

Why isn't change button content working

I have this code:
private void ModifyButton_Click(object sender, RoutedEventArgs e)
{
ModifyButton.Content = "Another button name";
}
But it doesn't work. I mean, the modify button content doesn't change but the program doesn't fail or throw any exception.
I'm trying to modify the button name in order to change it's behavior (kinda Edit/Save) within the same button. Is this not possible using C#/WPF?
Thanks in advance.
EDIT:
XAML:
<Button Name="ModifyButton" Content="Modificar" Margin="5,10,0,0" Height="23" Width="120" HorizontalAlignment="Left" Click="ModifyButton_Click"></Button>
WEIRD BEHAVIOR: If I put a MessageBox.Show call after the change of the button content, then, while the message box is displayed the button dislay the new (changed) name, but after the message box is closed, then it shows it's original text.
I guess that the XAML of your UI is not bound to the value of your button. Did you check the DataBinding?
[EDIT]
Your magic information here is that you use ShowDialog(). As you already guessed, this influences your UI thread and therefore the display behavior. ShowDialog() displays the Form as a modal dialog and blocks your UI thread and therefore blocks the refresh of it. This may cause all sorts of weird behavior.
This is what i have and it works:
Window 1
<Window x:Class="WpfApplication1.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">
<Grid>
<Button Name="ModifyButton" Content="Open Dialog" Margin="80,104,78,0" Height="23" Click="ModifyButton_Click" VerticalAlignment="Top"></Button>
</Grid>
</Window>
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void ModifyButton_Click(object sender, RoutedEventArgs e)
{
Window2 win2 = new Window2();
win2.ShowDialog();
}
}
Window 2
<Window x:Class="WpfApplication1.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window2" Height="300" Width="300">
<Grid>
<Button Name="ModifyButton" Content="Modificar" Margin="80,104,78,0" Height="23" Click="ModifyButton_Click" VerticalAlignment="Top"></Button>
</Grid>
</Window>
public partial class Window2 : Window
{
public Window2()
{
InitializeComponent();
}
private void ModifyButton_Click(object sender, RoutedEventArgs e)
{
ModifyButton.Content = "Another button name";
}
}

Categories