9

I have the following XAML in a WPF application. I would like to bind the button to an ICommand in a view model. For some reason, I am not able to see the command from my view. this is in a user control.

<Grid>
  <Grid.DataContext>
    <Binding x:Name="SettingsData"
             Path="Data"/>
  </Grid.DataContext>
...
  <DockPanel Grid.Column="1">
    <Button x:Name="SaveButton" 
            DockPanel.Dock="Top"  
            Height="25"  
            HorizontalAlignment="Left" 
            Margin="70 0 0 0"
            Command="{Binding Path=SaveData}">Save Changes</Button>
  </DockPanel>
</Grid>

Here is my ICommand object -

public ICommand SaveData
{
    get
    {
        if (_saveData == null)
        {
            _saveData = new RelayCommand(
                param => this.saveData(),
                param => true
                );
        }
        return _saveData ;
    }
}

Does anyone have any idea why I cannot bind to this command?

Thanks for any thoughts....

5
  • What is your implementation of RelayCommand, it does not belong to the standard WPF library? I would guess that CanExecute returns false. Commented Jul 5, 2011 at 14:18
  • I am using the relaycommand implementation from Josh Smith's MVVM tutorial - msdn.microsoft.com/en-us/magazine/dd419663.aspx. the second parameter is the CanExecute, so I am always sending in true.... Commented Jul 5, 2011 at 14:20
  • Can you see any binding errors in the VS Output window while debugging? Commented Jul 5, 2011 at 14:23
  • I see this in the output window - BindingExpression path error: 'SaveData' property not found on 'object' ''List`1' Commented Jul 5, 2011 at 14:26
  • Have you debugged the Binding with PresentationTraceSources.TraceLevel=High to see if everything is even working? Commented Jul 5, 2011 at 14:27

2 Answers 2

18

Looks like you are setting the DataContext of the Grid to the Data property of your ViewModel (or object). If the object that the Data property exposes doesn't provide the SaveData command, you'll have the problem you're describing. Remember the DataContext is inherited from the parent.

If you require that the DataContext is set in that manner, and still require the button to reference the parent DataContext, one option would be to use a RelativeSource to point to an element that has the ViewModel as the DataContext.

In WPF you also have the option of making those commands static and using the {x:Static} markup extension to reach it.

Hope that helps.

EDIT: Here's an example if your <Grid> is contained in a <UserControl>.

<Button Command="{Binding Path=DataContext.SaveData, 
                          RelativeSource={RelativeSource Mode=FindAncestor, 
                                          AncestorType={x:Type UserControl}}}" ... />

Also, I don't know what your full XAML looks like, but I suspect that this can be simplified greatly by removing the DataContext on the Grid and Binding Data on the ItemsControl (or whatever you're using to show the list of objects).

Sign up to request clarification or add additional context in comments.

7 Comments

The savedata command does reside in the same viewmodel that the grid is bound to. Shouldn't it be able to see it?
No, the DataContext of the Button is ViewModel.Data, not ViewModel. So, you're trying to bind to ViewModel.Data.SaveData. (And from your error, it seems like Data is a List of some object).
So do I have to set the datacontext of the button to the viewmodel?
Yes. But there are methods for getting it without explicitly setting it Xaml or code, including using RelativeSource or ElementName to point to a UIElement that already has the DataContext set to the ViewModel (most likely, the parent of Grid).
If I remove the datacontext from the grid as you mentioned above and put it at the list level, it works perfectly. Thank you for the help.
|
0

Looking at below error, looks like your DataContext on DockPanel is bound to some sort of List:

I see this in the output window - BindingExpression path error: 'SaveData' property not found on 'object' ''List`1'

Please override Source attribute in Binding if the DataContext is not at the top level

3 Comments

should I set the source to the name of the viewmodel?
i usually set the DataContext in code behind. How are u setting your View's DataContext?
I set it in the xaml of the view at the grid level as shown above

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.