3

I bind my wpf window to app layer class (WindowVM.cs) using DataContext in Window.xaml.cs constructor (DataContext = WindowVM). But, one control (btnAdd) I want to bind to Window.xaml.cs property. So in Window.xaml.cs constructor I add this.btnAdd.DataContext. This is Window.xaml.cs constructor and property to which I want bind Button btnAdd:

 public Window() { InitializeComponent(); DataContext = WindowVM; this.btnAdd.DataContext = this; } public RelayCommand Add { get { return _add == null ? _add= new RelayCommand(AddPP, CanAddPP) : _add; } set { OnPropertyChanged("Add"); } } 

Xaml looks like this (class PP is WindowVM property):

<TextBox Name="txtName" Text="{Binding PP.Name, ValidatesOnDataErrors=true, UpdateSourceTrigger=PropertyChanged}" /> <TextBox Name="txtSurname" Text="{Binding PP.Surname, ValidatesOnDataErrors=true, UpdateSourceTrigger=PropertyChanged}" /> <Button Command="{Binding Add}" Content="Add" ... /> 

And - everything works, but console output this:

BindingExpression path error: 'Add' property not found on 'object' ''WindowVM'... 

In next calls there isn't any console output error for property Add.

Now I am a little bit confused because of this error. Is this error because of first DataContext (to WindowVM), because there isn't property Add, but with line this.btnAdd.DataContext property Add is found and it's the reason that it works?

2
  • So why are you using MVVM(or a similar) if you aren't going to put the command in the ViewModel? The ViewModel should be where the Command is. There should really be ZERO code in the Window's code behind. Commented Sep 11, 2011 at 12:26
  • I put command in ViewModel, but have problems because I need to close window. This binding works: {Binding ElementName=MyUsersView, Path=Add}. But, I will try with this: blog.excastle.com/2010/07/25/… and put Command in ViewModel then. Commented Sep 14, 2011 at 18:11

3 Answers 3

2

Simply set the DataContext of the Button in the XAML using a RelativeSource:

<Button Command="{Binding Add}" Content="Add" DataContext="{Binding Add, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" /> 
Sign up to request clarification or add additional context in comments.

Comments

1

I had this problem and I know this is an oldish post but I think this might help someone who stumbles on this in the future.

what I did was declare the viewmodels as resources

<Page.Resources> <local:LocationListViewModel x:Key="LocationList" /> <local:LocationNewViewModel x:Key="NewLocation" /> <code:BinaryImageConverter x:Key="imgConverter" /> </Page.Resources> 

then which ever control I wanted to be associated with said viewmodel I added this to their datacontext

<TabItem x:Name="tabSettingsLocations" x:Uid="tabSettingsLocations" Header="Locations" DataContext="{StaticResource ResourceKey=LocationList}">.... <TabItem x:Name="tbSettingsLocationsAdd" x:Uid="tbSettingsLocationsAdd" Header="Add New" DataContext="{StaticResource ResourceKey=NewLocation}">.... <Image x:Name="imgSettingsLocationMapNew" x:Uid="imgSettingsLocationMapNew" Source="{Binding Map, Converter={StaticResource imgConverter}, Mode=TwoWay}" DataContext="{StaticResource ResourceKey=NewLocation}" /> 

So in my example above I have Listview bound to the list viewmodel and I create a new single location for my new entry. You will notice that by creating it as a resource I can bind the tabitem and the image (which is not a child of the tab item) to the new location viewmodel.

My command for the addnew location is in the new location viewmodel.

<TabItem x:Name="tbSettingsLocationsAdd" x:Uid="tbSettingsLocationsAdd" Header="Add New" DataContext="{StaticResource ResourceKey=NewLocation}">.... <Button x:Name="btnSettingsLocationSaveAdd" x:Uid="btnSettingsLocationSaveAdd" Content="Submit" Margin="0,80,10,0" VerticalAlignment="Top" Style="{DynamicResource ButtonStyle}" HorizontalAlignment="Right" Width="75" Command="{Binding AddCommand}" />..... 

Which is the child of the tabitem I bound to the new location viewmodel.

I hope that helps.

Comments

0

When you set the DataContext-Property, your Window resets the Bindings of it's child controls. Even the Binding of your button. At this Point (before "button.DataContext = this" is evaluated) "Add" is searched in WindowVM. After this you set the Window class as buttons DC, and everything works fine.

To avoid the initial error, swap two lines from this

public Window() { InitializeComponent(); DataContext = WindowVM; this.btnAdd.DataContext = this; } 

to this

public Window() { InitializeComponent(); this.btnAdd.DataContext = this; DataContext = WindowVM; } 

2 Comments

how can I set keybinding to this button now? <KeyBinding Command="{Binding SaveCommand}" Key="F8" /> not working
Your KeyBinding looks fine, but you still need to catch it with a CommandBinding <Window.CommandBindings> <CommandBinding Command={Binding SaveCommand} Executed="CommandExecuted_Handler" /> </Window.CommandBindings> Where "CommandExecuted_Handler" is the Event-Handler for it. You can find the Documentation here

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.