What is the best way to design a Key Pressed Control? - c#

I need to design a control that will capture the key stroke a user has pressed and treat that as the input.
I then need to display it to the user so they know which one they pressed.
I've tried using a textbox, and wiring up to the ValueChanged event, but it shows the key twice for some reason.
Does anyone know of a control that is already built that might handle this functionality?
Sidenote: I don't need an implementation with modifier keys or anything like that, I'm just trying to track a single key stroke for the time being.
Another way of looking at it is: In pretty much every PC video game, you can change the key bindings in the settings of the game. You go to the settings, find the key binding you're looking for, select it, and then hit a keystroke, then it captures that keystroke and changes the key binding to the keystroke the user entered.
That is exactly the functionality I'm looking for.

The simple way to do this would be data binding. In WPF this is quite easy. You can bind the data from one control to another. Below I have bound a TextBox, which has taken the user input, to a Label which displays it.
<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">
<Grid>
<TextBox Height="23" HorizontalAlignment="Left" Margin="45,55,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" />
<Label Content="{Binding ElementName=textBox1, Path=Text}" Height="28" HorizontalAlignment="Left" Margin="45,135,0,0" Name="label1" VerticalAlignment="Top" Width="142" />
</Grid>
The more complex answer would be to do Command binding. What this does is catches specific key bindings on a UserControl or Window and executes a given command. This is a little more complex because it requires you to create a class that implements ICommand.
More info here:
http://msdn.microsoft.com/en-us/library/system.windows.input.icommand.aspx
I personally am a big fan of the RelayCommand implementation by Josh Smith. There is a great article here.
In short though you can do this.
XAML:
<Window.InputBindings>
<KeyBinding Key="Escape" Command="{Binding KeyPressCommand}"/>
</Window.InputBindings>
CODE:
You will need to create a RelayCommand Class.
public class RelayCommand : ICommand
{
private readonly Action<object> _execute;
private readonly Predicate<object> _canExecute;
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
_execute(parameter);
}
public bool CanExecute(object parameter)
{
return _canExecute == null || _canExecute(parameter);
}
And then to implement this in your main window you will need to do this.
private RelayCommand _keyPressCommand;
public RelayCommand KeyPressCommand
{
get
{
if (_keyPressCommand== null)
{
_keyPressCommand = new RelayCommand(
KeyPressExecute,
CanKeyPress);
}
return _keyPressCommand;
}
}
private void KeyPressExecute(object p)
{
// HANDLE YOUR KEYPRESS HERE
}
private bool CanSaveZone(object parameter)
{
return true;
}
If you go with the second option I really suggest you take a look at the MSDN article by Josh Smith.

You have to catch the form event for this case,
Refer this Stack Overflow repeated question, it will provide you the answer
Fire Form KeyPress event

What I ended up having to do was this:
<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">
<Grid>
<TextBox Name="textBox1" PreviewKeyDown="previewKeyDown" />
</Grid>
and then in my even handler do this:
private void previewKeyDown(object sender, KeyEventArgs e)
{
e.Handled = true;
textBox1.Text = e.Key.ToString();
}
This basically disabled the default key functionality of the text box by setting
e.Handled = true
and then I changed the text of the textbox to be what I needed, which was the key that was pressed.

Related

WPF: How to implement Clear command

I'm learning WPF.
In one of the exercises, I have a TextBox and buttons Cut and Paste. The following is enough to implement Cut and Paste functionality:
XAML:
<DockPanel>
<WrapPanel DockPanel.Dock="Top" Margin="3">
<Button Command="ApplicationCommands.Cut"
CommandTarget="{Binding ElementName=txtEditor}"
Width="60">
_Cut
</Button>
<Button Command="ApplicationCommands.Paste"
CommandTarget="{Binding ElementName=txtEditor}"
Width="60" Margin="3,0">
_Paste<
/Button>
</WrapPanel>
<TextBox AcceptsReturn="True" Name="txtEditor" />
</DockPanel>
When pressed, the button Cut executes the ApplicationCommands.Cut on the TextBox with name txtEditor. When needed, the button will ask the TextBox with name textEditor if it can execute a Cut command, and when pressed it will order the textEditor to execute the Cut command.
Fairly straightforward. It works fine.
Just for Fun, I'd like to implement another button: Clear. When pressed it should clear the TextBox. The Textbox class has a method Clear.
<Button Command="ApplicationCommands.Clear"
CommandTarget="{Binding ElementName=txtEditor}"
Width="60">
Clear
</Button>
Alas, this won't work. ApplicationCommands doesn't have a Clear. Should I implement a custom command, as suggested in this example?
I tried the following:
I implemented CanExecute and Executed methods in my window:
public partial class CustomCommandSample : Window
{
public CustomCommandSample()
{
InitializeComponent();
}
private void ClearCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
private void ClearCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
txtEditor.Clear();
}
}
A static CustomCommands class:
public static class CustomCommands
{
public static RoutedUICommand Clear => new RoutedUICommand (
"Clear",
"Clear",
typeof(CustomCommands));
}
Finally the XAML:
(Note: the classes in this project are in namespace WpfCommandDemo. Xaml refers to it as Local)
<Window x:Class="WpfTutorialSamples.Commands.UsingCommandsSample"
xmlns="...
xmlns:local="clr-namespace:WpfCommandDemo"
Title="UsingCommandsSample" Height="100" Width="200">
<Window.CommandBindings>
<CommandBinding Command="CustomCommands.Clear"
CanExecute="ClearCommand_CanExecute"
Executed="ClearCommand_Executed" />
</Window.CommandBindings>
<DockPanel>
<WrapPanel DockPanel.Dock="Top" Margin="3">
<Button Command="CustomCommands.Clear"
CommandTarget="{Binding ElementName=txtEditor}"
Width="60">
Clear
</Button>
... (other buttons: cut / paste, as above
</WrapPanel>
<TextBox AcceptsReturn="True" Name="txtEditor" />
</DockPanel>
Although this compiles, The constructor of CustomCommandSample throws an XamlParseException:
Type reference cannot find type named
'{http://schemas.microsoft.com/winfx/2006/xaml/presentation}CustomCommands'.
Should I solve the problem using Custom Commands? What should I change? Or am I completely wrong, and should I solve this differently
To use CustomCommands in XAML, you'll need to add a reference to it. In the element, add a line:
xmlns:custom="clr-namespace:MyApplication.NamespaceWithCustomInIt"
Replacing the namespace value as appropriate. Then you should be able to reference CustomCommands anywhere in XAML as custom:CustomCommands (may have to bind, I'll check later).
Should I solve the problem using Custom Commands?
Yes. This is how to solve this using the Model-View-ViewModel (MVVM) design pattern which is the recommended design pattern to use when developing XAML based UI applications.
From this blog post:
WPF provides two implementations of the ICommand interface; the System.Windows.Input.RoutedCommand and System.Windows.Input.RoutedUICommand where the latter is a subclass of the former that simply adds a Text property that describes the command. However, neither of these implementations are especially suited to be used in a view model as they search the visual tree from the focused element and up for an element that has a matching System.Windows.Input.CommandBinding object in its CommandBindings collection and then executes the Execute delegate for this particular CommandBinding. Since the command logic should reside in the view model, you don’t want to setup a CommandBinding in the view in order to connect the command to a visual element. Instead, you can create your own command by creating a class that implements the ICommand. The below implementation is a common one that invokes delegates for the Execute and CanExecute methods:
public class DelegateCommand: System.Windows.Input.ICommand
{
private readonly Predicate<object> _canExecute;
private readonly Action<object> _execute;
public DelegateCommand(Action<object> execute)
: this(execute, null) { }
public DelegateCommand(Action<object> execute, Predicate<object> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter) => _canExecute == null ? true : _canExecute(parameter);
public void Execute(object parameter) => _execute(parameter);
public event EventHandler CanExecuteChanged;
public void RaiseCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
Once you have an implementation of the ICommand interface, it's easy to use in your view models:
public class ViewModel : INotifyPropertyChanged
{
public ViewModel()
{
ClearCommand = new DelegateCommand(Clear);
}
private string _text;
public string Text
{
get { return _text; }
set { _text = value; NotifyPropertyChanged(); }
}
public ICommand ClearCommand { get; }
private void Clear(object parameter)
{
Text = string.Empty;
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "") =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
In the view, you simply bind to the properties of the view model:
<TextBox AcceptsReturn="True" Name="txtEditor" Text="{Binding Text}" />
<Button Content="Clear" Command="{Binding ClearCommand}" />
Just remember to set the DataContext of the view to an instance of your view model for the bindings to work:
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel();
}

WPF UserControl, with Buttons and KeyBindings

I'm trying to implement a dialer in WPF. I have a window, and inside it a user control. The user control has lots of buttons, but the user can also use the num pad to enter numbers.
I created a small sample project to show where I'm at:
MainWindow.xaml
<Window x:Class="wpf_dialer.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:wpf_dialer"
Title="MainWindow" Height="200" Width="525">
<Window.Resources>
<local:DialerViewModel x:Key="myViewModel" />
</Window.Resources>
<Grid DataContext="{StaticResource myViewModel}">
<local:Dialer />
</Grid>
</Window>
Dialer.xaml
<UserControl x:Class="wpf_dialer.Dialer"
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"
xmlns:local="clr-namespace:wpf_dialer"
mc:Ignorable="d"
d:DesignHeight="200" d:DesignWidth="300"
d:DataContext="{d:DesignInstance local:DialerViewModel}"
Loaded="UserControl_Loaded">
<UserControl.InputBindings>
<KeyBinding Key="A" Command="{Binding CommandDialValue, Mode=OneTime}" CommandParameter="." />
<KeyBinding Key="Back" Command="{Binding CommandDialValue, Mode=OneTime}" CommandParameter="Back" />
<KeyBinding Key="Enter" Command="{Binding CommandAcceptValue, Mode=OneTime}" CommandParameter="KeyBinding" />
</UserControl.InputBindings>
<UniformGrid Columns="1">
<TextBox IsEnabled="False" Text="{Binding DialedValue, Mode=OneWay}" MinWidth="200" FontSize="20" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="10"/>
<Button Content="OK" Margin="60,30" Command="{Binding CommandAcceptValue, Mode=OneTime}" CommandParameter="Button" />
</UniformGrid>
</UserControl>
DialerViewModel.cs
using System;
using System.ComponentModel;
using System.Windows.Input;
namespace wpf_dialer
{
class DialerViewModel : INotifyPropertyChanged
{
private Random RAND = new Random();
private string _dialed_value = "00";
public string DialedValue
{
get { return _dialed_value; }
set
{
if (_dialed_value == value) return;
_dialed_value = value;
RaisePropertyChanged("DialedValue");
}
}
public ICommand CommandDialValue { get { return new CommandImpl(DialValue); } }
public ICommand CommandAcceptValue { get { return new CommandImpl(Alert); } }
private void DialValue(object parameter)
{
if (parameter.ToString() == "Back")
{
if (DialedValue.Length > 0)
{
DialedValue = DialedValue.Substring(0, DialedValue.Length - 1);
}
}
else
{
DialedValue += RAND.Next(0, 10).ToString();
}
}
private void Alert(object parameter)
{
System.Windows.MessageBox.Show(parameter.ToString());
}
#region INotifyPropertyChanged
protected void RaisePropertyChanged(string property_name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property_name));
}
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion
private class CommandImpl : ICommand
{
private readonly Action<object> _action = null;
public CommandImpl(Action<object> action)
{
_action = action;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter) { return true; }
public void Execute(object parameter) { _action(parameter); }
}
}
}
Objectives:
As soon as the window is loaded, when the user presses the A key, the CommandDialValue is executed;
When the user presses Enter, a message box is displayed with the text "KeyBinding". The CommandAcceptValue must be called from the KeyBinding, and NOT from the button;
Problems:
When the window is loaded, the KeyBindings don't execute. They are executed when I click a button somewhere in the UserControl;
When I press Enter, the button's command is executed, but I want the user control's KeyBinding to be executed;
This dialer must be held in a UserControl (or a ControlTemplate, or DataTemplate), because it's contained in a very elaborate window.
I don't want to put the KeyBindings on the Window, because then the UserControl is not reusable, and because its DataContext is not the same as the user control.
UPDATE:
I solved the second problem by setting Focusable="False" on all buttons.
To prevent the buttons from gaining focus, I set Focusable="False" for all buttons.
To set the focus when the window opens, I set Focusable="True" on the UserControl, and on the Loaded event I called Focus().
Dialer.xaml
d:DataContext="{d:DesignInstance local:DialerViewModel}"
Loaded="UserControl_Loaded" Focusable="True">
<UserControl.InputBindings>
Dialer.xaml.cs
private void UserControl_Loaded(object sender, RoutedEventArgs e) {
Focus();
}
I found no combination of FocusManager.FocusedElement that worked. I tried {Binding ElementName=myUserControl}, and {Binding RelativeSource={RelativeSource Self}}.
It's a question of Focus. When your window is loaded for the first time, your user control does not have Focus. So key bindings' gesture will not intercept your keypress. You have, at the first app loading time, to give Focus to your user control. (Focusable ="True"(i don't know if this helps but i am sure the FocusManager will helps)). Then your key gestures will work well.

When does binding actually happen

On a popup window I have a checkbox.IsChecked bound to a model, but I want to check its state from the xaml code behind when the window is displayed. When checking the checkbox by name in the code behind from the windows loaded event it is not set yet. There are some UI specific things that I need to do and that is why I need to know what the checkboxes value is when the window opens and i cannot perform this from the model that the checkbox.IsChecked is bound to.
The property on the model is set long before the popup window is opened, so it is not an issue of the binding not being there. I figured that once the Loaded event fires the window would be ready to use bindings and all, but this does not seem to be the case.
Xaml:
<RefinedRibbonControls:RefinedRibbonGroup Header="Show Graphs">
<StackPanel x:Name="panelVisibilities">
<CheckBox Content="Show/hide" x:Name="myCheckBox"
IsChecked="{Binding Path=Processor.Model.IsItemVisible}"
Click="GraphVisibilityClickEvent"
HorizontalAlignment="Left"/>
...etc
Property on model:
public bool IsItemVisible
{
get { return _isItemVisible ; }
set
{
if (_isItemVisible != value)
{
_isItemVisible = value;
_propertyChanger.FirePropertyChanged(this, m => m.IsItemVisible);
}
}
}
Event in Xaml codebehind:
private void WindowLoadedEvent(object sender, RoutedEventArgs e)
{
if(myCheckBox.IsChecked.Value)
{
// Do UI Related Stuff
}
}
The binding works fine and the values show up when the window is displayed, the problem is I cannot get the value of the binding in the window loaded event.
Edit: Possible solution I have found but I am not sure if its the best way.
I called the following method from the constructor on the xaml code behind.
private void SetupInitialVisibility()
{
//Fire after everything is loaded.
Dispatcher.BeginInvoke(DispatcherPriority.ContextIdle, new Action(() =>
{
IEnumerable<CheckBox> elements = this.panelVisibilities.Children.OfType<CheckBox>().ToList();
foreach (CheckBox checkBox in elements)
{
if (checkBox.IsChecked != null && checkBox.IsChecked.Value == false)
{
//Do work
}
}
}));
}
found at: https://stackoverflow.com/a/1746975/1253746
Data binding is not done synchronously, but it is delayed. Check this msdn page on dispatcher priorities. It is done at a lower priority than normal window messages, but before rendering.
You could invoke a method on yourself with a lower priority than is defined for databinding, in this method you should be able to safely read the data bound value.
I would still find this ugly. I'd rather subscribe directly to PropertyChanged and check for this property, or even better, rewrite your "UI related code" as a data binding.
P.S. If you start consuming events, be sure to unsubscribe, or you might get memory leaks.
DataBinding should precede the Loaded event I think.
When and how do you set your DataContext? And you are positive that the viewmodel property is already set?
The following works, try to align your code with this if possible.
Xaml:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:ViewModel />
</Window.DataContext>
<Grid>
<CheckBox x:Name="myCheckBox" IsChecked="{Binding IsItemVisible}" />
</Grid>
</Window>
Code Behind:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.Loaded += MainWindow_Loaded;
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
if (myCheckBox.IsChecked.Value)
{
//...
}
}
}
ViewModel:
public class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private bool isItemVisible;
public bool IsItemVisible { get { return isItemVisible; } set { isItemVisible = value; OnPropertyChanged("IsItemVisible"); } }
public ViewModel()
{
this.IsItemVisible = true;
}
private void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}

Button not enabled even after providing CommandParameter in WPF

I created a button whose commandparameter is set and command using a class that implements ICommand interface. But my button is disabled. Why is that? I got this code from here: ICommand is like a chocolate cake
<Window x:Class="ICommand_Implementation_CSharp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ICommand_Implementation_CSharp"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid>
<Grid.Resources>
<local:HelloWorldCommand x:Key="hwc" />
</Grid.Resources>
<Button Command="{StaticResource hwc}" CommandParameter="Hello"
Height="23" HorizontalAlignment="Left" Margin="212,138,0,0"
Name="Button1" VerticalAlignment="Top" Width="75">Button</Button>
</Grid>
</Grid>
and my class is
class HelloWorldCommand:ICommand
{
public bool CanExecute(object parameter)
{
return parameter != null;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
MessageBox.Show(parameter.ToString());
}
}
Well, this is very-very simple implementation of ICommand.
As #JleruOHeP says, partially problem can be solved by swapping setters of Command and CommandParameter. But this is ugly way, because you have to remember the sequence every time.
More correct way is to tell CommandManager to re-query states of command:
public class HelloWorldCommand : ICommand
{
public bool CanExecute(object parameter)
{
return parameter != null;
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
MessageBox.Show(parameter.ToString());
}
}
Now the sequence of setters is indifferent.
To understand how CommandManager works, you can read this nice article from Josh Smith.
The simplest answer - switch places of Command and Command parameter:
<Button CommandParameter="Hello" Command="{StaticResource hwc}" .../>
But better one is given by #Dennis
In my case it was the CommandParameter type that was causing the issue. My button was simply bound like this:
<Button Content="New" Command="{Binding NewCommand}" CommandParameter="False" />
The underlying NewCommand is a RelayCommand<bool>. Somehow XAML was not able to translate False to bool. (Note that it does work for many built-in types and properties; maybe some TypeConverter or something at action there).
Solution was to simply spoon-feed XAML about the real underlying type of CommandParameter, like this:
<Button Content="New" Command="{Binding NewCommand}">
<Button.CommandParameter>
<sys:Boolean>
False
</sys:Boolean>
</Button.CommandParameter>
</Button>
You have to import sys namespace at the top of your XAML file, like this:
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Hope this helps someone down the road.

Two views referring same view model

I'm using two views which refers same view model. Both of my views contain a text box that binds to a value in the view model. My problem is that, if I change the value of textbox in one GUI, its not reflecting in another. What should I do to achieve this?
This is my view model
public class ProductViewModel:INotifyPropertyChanged
{
private int machineheight;
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
public int MachineHeight
{
get
{
return this.machineheight;
}
set
{
this.machineheight = value;
RaisePropertyChanged("MachineHeight");
}
}
public ProductViewModel()
{
}
private ICommand mUpdater;
public ICommand UpdateCommand
{
get
{
if (mUpdater == null)
mUpdater = new Updater();
return mUpdater;
}
set
{
mUpdater = value;
}
}
private class Updater : ICommand
{
#region ICommand Members
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
SecondWindow w = new SecondWindow();
w.Show();
}
#endregion
}
}
}
The second window is another GUI. Once I click update button, second window opened. But the value that I have changed in first UI is not updated in the new window.
My Xaml is similar for both UI..
<Window x:Class="WPFDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPFDemo"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:ProductViewModel/>
</Window.DataContext>
<Grid Height="307" Width="480" Initialized="Grid_Initialized">
<Button Content="Update" Height="32" HorizontalAlignment="Left" Margin="165,158,0,0" Name="button1" VerticalAlignment="Top" Width="114" Command="{Binding Path=UpdateCommand}"/>
<TextBox Height="42" HorizontalAlignment="Left" Margin="125,82,0,0" Name="textBox1" VerticalAlignment="Top" Width="169" Text= "{Binding Path= MachineHeight, Mode=TwoWay}" />
</Grid>
</Window>
I actually don't know what is the problem.. thanks
<Window.DataContext>
<local:ProductViewModel/>
</Window.DataContext>
hi, if you put this in your 2 views, then each one has its own viewmodel. so you will never see any changes. you have to set the datacontext from your first view to your second view. Btw for your ICommand implementation look at some mvvm frameworks for easier implementations, eg RelayCommand, DelegateCommand.
For your actual implementation you can add the following to your xaml and ViewModel(CommandParameter) then it works.
<Button Content="Update" Height="32" HorizontalAlignment="Left" Margin="165,158,0,0" Name="button1" VerticalAlignment="Top" Width="114" Command="{Binding Path=UpdateCommand}"
CommandParameter="{Binding .}"/>
public void Execute(object parameter)
{
SecondWindow w = new SecondWindow();
w.DataContext = parameter;
w.Show();
}
There are a hundred things that can go wrong in this scenario, and one of my long-standing gripes with XAML-based databinding is that the MS tools give you precious little help figuring out which of those hundred things it is. This is especially the case if you're new to databinding, but even folks who've been doing it for years can spend obnoxious hours tracking down databinding issues.
Some things to check:
(1) Confirm that your databindings are two-way.
(2) Look in your debug output window to see if there are any error messages there.
(3) Set an IValueConverter in your databinding, and set a breakpoint in the converter to see what data is being passed where and when.
(4) Confirm that the data in the ViewModel is actually being updated.
(5) Confirm that the ViewModel implements INotifyPropertyChanged, and that the PropertyChanged event is firing.
(6) Post your actual code here so folks can look at it.
And so forth.
Hope this helps.
It must work if the ViewModel implements INotifyPropertyChanged.

Categories

Resources