Binding Dependency Property to Current DataContext Property - c#

I keep trying to make this hurdle in WPF, and I think I've found a solution, albeit an ugly one.
The scenario is as follows:
I have a custom user control with a custom dependency property.
The user controls can be nested inside of my other user controls.
Each of my user controls has a data context that is specified by a locator (I am following the MVVM pattern)
I want to bind the custom dependency property to a value in the parent view model.
Code...
Parent View
<UserControl DataContext="{Binding Source={StaticResource Locator}, Path=ParentControlLocator}">
<my:Child Demo="{Binding Path=DataContext.DemoTextAlpha, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl, AncestorLevel=1}}" />
</UserControl>
Parent Class View Model
public class ParentClassViewModel : BaseViewModel
{
private string _demoTextAlpha = "Some Alpha text";
public string DemoTextAlpha
{
get
{
return this._demoTextAlpha;
}
set
{
this._demoTextAlpha = value;
this.NotifyPropertyChange("DemoTextAlpha");
}
}
}
Child View
<UserControl DataContext="{Binding Source={StaticResource Locator}, Path=ChildControlLocator}">
<TextBlock Text="{Binding Path=SomeProperty}" />
</UserControl>
Child View Code Behind
public partial class Child : UserControl
{
public Child()
{
InitializeComponent();
}
public static readonly DependencyProperty DemoProperty =
DependencyProperty.Register("Demo",
typeof(string),
typeof(Child),
new FrameworkPropertyMetadata()
{
PropertyChangedCallback = OnDemoChanged,
BindsTwoWayByDefault = true
});
public string Demo
{
get { return this.GetValue(DemoProperty).ToString(); }
set { this.SetValue(DemoProperty, value); }
}
private static void OnDemoChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = (Child)d;
var viewModel = (ChildViewModel)control.DataContext;
viewModel.SomeProperty = (string)e.NewValue;
}
}
Child View Model
public class ChildViewModel : BaseViewModel
{
private string _someProperty;
public string SomeProperty
{
get
{
return _someProperty;
}
set
{
_someProperty = value;
this.NotifyPropertyChange("SomeProperty");
}
}
}
Ok, so this WORKS. What I'm trying to achieve is better/ more elegant code, particularly as it regards to this statement.
<my:Child Demo="{Binding Path=DataContext.DemoTextAlpha, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl, AncestorLevel=1}}" />
Even that I could live with, as far as elegance goes, but one thing that is bothering me right now is that when I type
Path=DataContext.DemoTextAlpha
The intellisense drops when I try to drill down inside the DataContext. So I have to be extra careful to type everything right.
So - is there any different way to make the properties of the DataContext appear in intellisense, or is there an alternative way to achieve the same thing that I'm doing now?
Thanks.
EDIT to Clarify
When I put something like this instead of specifying the relative source as in the above examples...
<my:Child Demo="{Binding DemoTextAlpha}"/>
I receive an error...
System.Windows.Data Error: 40 : BindingExpression path error: 'DemoTextAlpha' property not found on 'object' ''ChildViewModel' (HashCode=34126977)'. BindingExpression:Path=DemoTextAlpha; DataItem='ChildViewModel' (HashCode=34126977); target element is 'Child' (Name=''); target property is 'Demo' (type 'String')

The DataContext (along with a lot of other properties such as FontSize) is "Inherited" along the visual tree. Therefore this:
<UserControl DataContext="{Binding Source={StaticResource Locator}, Path=ParentControlLocator}">
<my:Child Demo="{Binding Path=DataContext.DemoTextAlpha, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl, AncestorLevel=1}}" />
</UserControl>
Is exactly the same as this:
<UserControl DataContext="{Binding Source={StaticResource Locator}, Path=ParentControlLocator}">
<my:Child Demo="{Binding DemoTextAlpha}"/>
</UserControl>
With regards to the Intellisense support, I don't know what VS version you're using, but I'm using VS 2010 Pro with ReSharper 6.1 and it adds Intellisense support if you specify the d:DataContext value:
<UserControl x:Class="...etc."
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TheViewModelNamespace"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d" d:DataContext="{d:DesignInstance local:ViewModel}">
Edit:
Ok.. let's analize what you're doing here:
1 - Binding the UserControl to the ParentVM:
ParentVM -> UserControl
2 - Using RelativeSource To Grab some property from ParentVM and place it into a Custom DP you created in the Child control
ParentVM -> UserControl -> Child Control
3 - In the OnPropertyChanged of the custom DP, setting that same value to the ChildVM
ParentVM -> UserControl -> Child Control -> ChildVM
Do you realize you're using the View (User Control, Child Control) as an intermediate to share some properties between 2 View Models? Why don't you just
ParentVM -> ChildVM
Which would be easier, cleaner and really MVVM?
Either put a reference from the ParentVM directly to the ChildVM, or use something like a Messenger pattern to have indirect communication between them.

DataContext is inherited:
<UserControl DataContext="{Binding Source={StaticResource Locator}, Path=ParentControlLocator}">
<my:Child Demo="{Binding DemoTextAlpha}" />
</UserControl>
If, ina different scenario, your child control has a different DataContext specified and you still need to bind to a property of your parent control's DataContext, using ElementName is probably nicer:
<UserControl x:Name="Parent" DataContext="{Binding Source={StaticResource Locator}, Path=ParentControlLocator}">
<my:Child Demo="{Binding Path=DataContext.DemoTextAlpha, ElementName=Parent}" />
</UserControl>

Related

WPF user control properties not binding or updating

I'm messing around with WPF and creating User Controls but having a hard time understanding how the databinding is supposed to work. Data binding seems to be overly complex and as long as WPF has been out I would think MS would've created some shortcuts to prevent having to do so much boilerplate code.
User control xaml
<UserControl x:Class="WPFTest.FancyBox"
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">
<DockPanel>
<Label Content="{Binding MyText}"></Label>
</DockPanel>
</UserControl>
User control .cs
public partial class FancyBox : UserControl
{
public static readonly DependencyProperty MyTextProperty = DependencyProperty.Register("MyText", typeof(string), typeof(FancyBox), new PropertyMetadata(null));
public string MyText
{
get => (string)GetValue(MyTextProperty);
set => SetValue(MyTextProperty, value);
}
public FancyBox()
{
InitializeComponent();
}
}
Usage in my main window
<StackPanel>
<local:FancyBox MyText="testing!"/>
</StackPanel>
The binding Content="{Binding MyText}" is binding to the DataContext of the control (Label) which is inherited from closest ancestor up the tree who have one (your code doesn't show any DataContext assignment)
Your intended behavior is for Label's Content to bind to the User Control's Property in this case you need to make the user control your source. Many ways to do this for example:
<UserControl x:Class="WPFTest.FancyBox"
x:Name="RootElement"
....
<Label Content="{Binding MyText, Source={x:Reference RootElement} />
Or another way:
<Label Content="{Binding MyText, RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type local:FancyBox}}" />
Keep in mind any Bindings without a source (Source, RelativeSource) will source from DataContext.
I guess I didn't need data binding for this at all
I changed my controls label to:
<Label x:Name="lblText"></Label>
and my code-behind to:
public string MyText
{
get => lblText.Content.ToString();
set => lblText.Content = value;
}

How to use ElementName binding from resource?

I've added a MenuFlyout to a button in ItemsControl.ItemTemplate. Also I was able to bind current item as CommandParameter.
Now I want to bind Command to a MenuFlyoutItem.
In codebehind :
LayoutRoot.DataContext = this;
So if i bind to LayoutRoot I will actually bind to my current UserControl. But the following binding is not working:
Command="{Binding ActivateProfileCommand, ElementName=LayoutRoot}"
It gives me not errors in Output but it's not working.
Here's the full example:
<controls:HeaderDecorator x:Uid="AccountsHeader" Text="Accounts" x:Name="LayoutRoot" Name="LayoutRoot">
<controls:HeaderDecorator.Resources>
<MenuFlyout x:Key="AccountMenuFlyout">
<MenuFlyoutItem Text="Activate" Name="Activate"
Command="{Binding ActivateProfileCommand, ElementName=LayoutRoot}"
CommandParameter="{Binding}" />
</MenuFlyout>
</controls:HeaderDecorator.Resources>
<StackPanel Orientation="Vertical">
<ItemsControl ItemsSource="{Binding Settings.Profiles}" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<HyperlinkButton Content="{Binding}" FlyoutBase.AttachedFlyout="{StaticResource AccountMenuFlyout}" >
<i:Interaction.Behaviors>
<ic:ShowFlyoutBehavior />
</i:Interaction.Behaviors>
</HyperlinkButton>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</controls:HeaderDecorator>
Seems the problem is i'm trying to use shared object in Resources. Can I do it? And why not?
The issue you are seeing here is the MenuFlyoutItem is no longer in the datacontext you perhaps think it is. I'll try and explain this as best I can as a few I know who work with xaml have come across this and hit their heads off walls for days about it. It's also known to not show errors in your particular scenario; further increasing confusion.
In a nutshell. When the MenuFlyout is added inside the ItemTemplate of each item in your collection, it does not have access to the datacontext you perhaps think it does. In this case, the datacontext that the control now resides is actually the individual item within the collection it is sitting in.
There is however a solution to this. I have something similar to yourself. An ItemsControl which has it's ItemsTemplate defined that includes a UIElement who's FlyoutBase AP references a MenuFlyout defined in a resource dictionary.
The xaml is pretty much the same except I don't need the ElementName in the binding.
However, I have now turned my attention to the type that the collection holds. I have code that looks something like this.
public class AnItemToList
{
public AnItemToList(Action commandDel)
{
TestCommand = new RelayCommand(commandDel);
}
public string Name { get; set; }
public RelayCommand TestCommand { get; set; }
}
Note that the command is being defined in the item itself and that I'm passing the method that the command will execute via the constructor.
All I have to do for the command binding on the MenuFlyoutItem is
<MenuFlyoutItem Text="Activate"
Name="Activate"
Command="{Binding TestCommand}"/>
I don't have a command param set here as I just quickly put together a basic template Windows Phone app and the pre-packed ICommand implementation doesn't have a delegate set to take the param.
If you now stick a break point in the method the command is calling, you'll see it will be called from any of the MenuFlyoutItem's bound to the command that references it.
Bare in mind that this isn't the only way of solving this problem; but it is one I use myself on occasion. For example, in WPF XAML you can make use of RelativeSource to go looking for the command on a parent control's datacontext.
Hope this helps.
Here's a general "Pair" object:
public class Pair : DependencyObject
{
public static readonly DependencyProperty FirstProperty = DependencyProperty.Register("First",
typeof(object), typeof(Pair), new PropertyMetadata(null));
public static readonly DependencyProperty SecondProperty = DependencyProperty.Register("Second",
typeof(object), typeof(Pair), new PropertyMetadata(null));
public object First
{
get { return GetValue(FirstProperty); }
set { SetValue(FirstProperty, value); }
}
public object Second
{
get { return GetValue(SecondProperty); }
set { SetValue(SecondProperty, value); }
}
}
In ItemTemplate i put something like this:
<DataTemplate>
<Grid>
<Grid.Resources>
<viewModel:Pair x:Key="Tuple" First="{Binding DataContext, ElementName=LayoutRoot}"
Second="{Binding}" />
</Grid.Resources>
<HyperlinkButton Content="{Binding Second.ProfileName}"
DataContext="{StaticResource Tuple}"
FlyoutBase.AttachedFlyout="{StaticResource AccountMenuFlyout}"
</HyperlinkButton>
</Grid>
</DataTemplate>
Now I can easily reference Tuple elements from my Resource like this:
<MenuFlyoutItem Text="Activate" Name="Activate"
Command="{Binding First.ActivateProfileCommand}"
CommandParameter="{Binding Second}" />

Binding to UserControl DependencyProperty

I have created a UserControl with some DependencyProperties (in the example here only one string property). When I instantiate the Usercontrol, I can set the property of the UserControl and it is shown as expected. When I am trying to replace the static text by Binding, nothing is displayed.
My UserControl looks as follows:
<User Control x:Class="TestUserControBinding.MyUserControl"
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="30" d:DesignWidth="100">
<Grid>
<Label Content="{Binding MyText}"/>
</Grid>
</UserControl>
The Code Behind is:
namespace TestUserControBinding {
public partial class MyUserControl : UserControl {
public MyUserControl() {
InitializeComponent();
this.DataContext = this;
}
public static readonly DependencyProperty MyTextProperty =
DependencyProperty.Register(
"MyText",
typeof(string),
typeof(MyUserControl));
public string MyText {
get {
return (string)GetValue(MyTextProperty);
}
set {
SetValue(MyTextProperty, value);
}
}// MyText
}
}
When I try this in my MainWindow, everything is as expected:
<Window x:Class="TestUserControBinding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestUserControBinding"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<local:MyUserControl MyText="Hello World!"/>
</StackPanel>
</Window>
But this doesn't work:
<Window x:Class="TestUserControBinding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestUserControBinding"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<local:MyUserControl MyText="{Binding Path=Text}"/>
<Label Content="{Binding Path=Text}"/>
</StackPanel>
</Window>
The behaviour of the label is correct, so there is no Problem with the Property "Text"
What is my mistake?
With the following binding in your UserControl:
<Label Content="{Binding MyText}"/>
I'm not sure how setting the text directly to the MyText property works. You must be setting the DataContext on the UserControl somewhere for this to work.
Regardless, this binding is the issue - as I understand your scenario, you don't want to bind to the DataContext of the UserControl because that will not necessarily have a MyText property. You want to bind to the UserControl itself, and specifically the DependencyProperty you created. To do that, you need to use a RelativeSource binding, like the following:
<Label Content="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:MyUserControl}}, Path=MyText}"/>
This will navigate up the visual tree to MyUserControl and then find the MyText property there. It will not be dependent on the DataContext, which will change based on where you place the UserControl.
In this case, local refers to a namespace you'll need to define in the UserControl:
<UserControl x:Class="TestUserControBinding.MyUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestUserControBinding"
...>
And your second example should work at that point.
There is a misunderstanding of how DataContexts are set. This is working against you...
Ultimately the binding to MyText on the user control, is not bound to the control's MyText dependency property but to the page's DataContext and there is no MyText property.
Let me explain
Explanation When the user control is put on your main page, it inherits its controls parent's DataContext (the StackPanel). If the parent's DataContext is not set, it will move up the chain to the StackPanel's parent's DataContext (ad Infinium) until it gets to the page's DataContext (which in your example is set and valid).
When you bind on the main page such as <local:MyUserControl MyText="{Binding Path=Text}"/> it looks for Text property on the main pages DataContext and sets the dependency property MyText to that value. Which is what you expect and it works!
Current State
So the state of the user control in your code is this, its DataContext is bound to the page's DataContext and MyText dependency property is set. But the internal control's binding to MyText fails. Why?
The user control has the parent's data context, and you are asking the control to bind to a MyText property on that data context. There is no such property and it fails.
Resolution
To bind to the control's instance and get the value from MyText property, just put a name (an element name) on the control such as
<User Control x:Class="TestUserControBinding.MyUserControl"
...
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
x:Name="ucMyUserControl"
and then properly path the binding away from the default DataContext and to the elementnamed named instance called ucMyUserControl. Such as:
<Label Content="{Binding MyText, ElementName=ucMyUserControl }"/>
Note that VS2017/2019 will actually intellisense the ElementName after you have named the control.
Side Effect of Just Using The Parents Data Context
A side effect of the original situation without the resolution mentioned, is that you could just bind the user control's binding to Text and it will work because the binding is defaulting to the page's datacontext. Subtle...
<User Control x:Class="TestUserControBinding.MyUserControl"
mc:Ignorable="d"
d:DesignHeight="30" d:DesignWidth="100">
<Grid>
<Label Content="{Binding Text}"/>
That works and technically you could remove the dependency property. If the control is not used outside the project, it could be designed to bind to other named properties with no ill effect as well.
Then all usercontrols could become defacto sub controls of the main page, as if you just pasted the internal XAML onto the page.

Setting ViewModel's Property from XAML

I have some UserControl, It's DataContext is binded to the ViewModel,
How to set a ViewModel's property from XAML? Is it possible?
UPD :
Sorry for being not very clear,
I'm trying to get something like this :
UserControl's DataContext is binded to ViewModel, I need to set ViewModel's property to something (let's say, UserControl's Width property).
Is it possible?
UPD2: It seems to be not possible.I know about TwoWay binding mode, etc, thing I wanted to do - to set ViewModel's property to UserControl's one
This example should be very clear
<Set Property={Binding SomePropertyOnViewModel}
Value={Binding RelativeSource={RelativeSource Self},
Path=SomePropertyOnUserControl}>
I am not sure whether I understand the question exactly.
But here is an example.
It will:
Create a view model of type ExampleViewModel inside the user control by setting the user
controls DataContext property in xaml
Create a text box in xaml and bind it to the view models
TextInViewModel string property.
Set up the usual INotifyPropertyChanged interface (this was extracted to the base class ViewModelBase)
Create the view model in xaml and set the user controls data context to it:
<UserControl x:Class="MyUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Test"
xmlns:viewModel="clr-namespace:ViewModels">
<UserControl.DataContext>
<viewModel:ExampleViewModel/>
</UserControl.DataContext>
<StackPanel Orientation="Horizontal" >
<Label>Enter Text here: </Label>
<TextBox Text="{Binding TextInViewModel}"></TextBox>
</StackPanel>
</UserControl>
ViewModel:
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string prop)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(prop));
}
}
}
public class ExampleViewModel : ViewModelBase
{
/// <summary>
/// Property bound to textbox in xaml.
/// </summary>
public String TextInViewModel
{
get { return _textInViewModel; }
set
{
_textInViewModel= value;
RaisePropertyChanged("TextInViewModel");
}
}
private string _textInViewModel;
/// <summary>
/// Constructor.
/// </summary>
public ExampleViewModel()
{
}
}
Binding works both ways: i.e. from source (e.g. viewmodel) to target (e.g. usercontrol) and from target back to source.
You specify the direction via Mode of binding.
Following are the BindingModes:
TwoWay
OneWay
OneTime
OneWayToSource
In your case, if you want to bind width property of usercontrol to the TheWidth property of ViewModel:
Case A:
Want to bind in both directions, use Mode=TwoWay
<UserControl Width="{Binding TheWidth, Mode=TwoWay}">
<!-- your rest of code -->
</UserControl>
Case B:
Want to bind only from usercontrol to viewmodel, use Mode=OneWayToSource
<UserControl Width="{Binding TheWidth, Mode=OneWayToSource}">
<!-- your rest of code -->
</UserControl>
XAML
<UserControl.DataContext>
<vm:ViewModel/>
</UserControl.DataContext>
I prefer the ViewModel Locator approach (this is like a service locator pattern for ViewModel).
Because as soon as your ViewModel has constructor parameters, you are either tightly coupled, or you can't use the above described xaml way....
There are many ViewModel-Locator ways. One is described here using MEF and silverlight.
http://johnpapa.net/simple-viewmodel-locator-for-mvvm-the-patients-have-left-the-asylum
here is another one:
http://brendan.enrick.com/post/Wire-up-your-ViewModels-using-a-Service-Locator.aspx
Well, you bind your UI elements to them:
<UserControl Width="{Binding Path=DisplayWidth, Mode=OneWayToSource}">
<Grid>
<TextBox MinWidth=100 Text="{Binding MyProperty}"/>
</Grid>
</UserControl>
assuming a view model like this:
class ViewModel
{
public string MyProperty { get; set; }
public int DisplayWidth { get; set; }
}
Through binding my dear friend..
for example: (Assuming in your context)
If you have class "Person" and your person has a Name and SurName public property and you want to bind it to a textbox. You do the following:
<TextBox Text="{Binding Path=Name}" />
This only works if the name is your public property, it is best practice to make you object ( in this case Person) as a public property and use the Path parameter differently.
Example:
<TextBox Text="{Binding Path=Person.Name}" />
It does clutter your code way less, then to make a property in your viewmodel for every property of any object in your viewmodel.
"How to set a ViewModel's property from XAML? Is it possible?"
So, that seems to be not possible, max you can accomplish - two-way binding, which is, unfortunately not I wanted.
All in all it's rather bad design than a problem

Binding with ElementName in the nested UserControls

I have the following simple code:
<Window x:Class="WpfApplication3.MainWindow"
x:Name="WindowInst" …>
<local:UserControl1/>
</Window>
<UserControl x:Class="WpfApplication3.UserControl1" …>
<Button Content="Click me"
Command="{Binding DataContext.ButtonClickedCommand,
ElementName=WindowInst}" Height="134" Width="314" />
</UserControl>
And in the ViewModel for the Window I have ButtonClickedCommand:
#region Avatar click command
RelayCommand _buttonClickedCommand;
public ICommand ButtonClickedCommand
{
get
{
if (_buttonClickedCommand == null)
{
_buttonClickedCommand = new RelayCommand(() => this.ButtonClicked());
}
return _buttonClickedCommand;
}
}
public void ButtonClicked()
{
}
#endregion
Unfortunately, it causes exception at runtime:
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=WindowInst'. BindingExpression:Path=DataContext.ButtonClickedCommand; DataItem=null; target element is 'Button' (Name=''); target property is 'Command' (type 'ICommand')
Could you explain me what’s wrong with it?
Try modifying your binding as follows...
<Window x:Class="WpfApplication3.MainWindow"
x:Name="WindowInst" …>
<local:UserControl1/>
</Window>
<UserControl x:Class="WpfApplication3.UserControl1" …>
<Button Content="Click me"
Command="{Binding Path=ButtonClickedCommand, Mode=FindAncestor, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" Height="134" Width="314" />
</UserControl>
This should work as WindowInst does not live within Self since your container is the UserControl; which is being placed within the Window. In addition you need to make sure that you are setting your DataContext within the Window or its value will be null and no binding will ever occur no matter if your syntax is accurate or not.
Your bindings are a little off.
Please see this tutorial on WPF command binding.
As a general rule, specify as little as possible in your bindings. I don't think you need element name in this circumstance and datacontext is the assumed root of your bindings.

Categories