0
votes

I create a VM based on MVVM light toolkit. In VM, there is a simple ICommand(RelayCommand)

  private RelayCommand _myCommand = null;
    public RelayCommand MyCommand
    {
        get
        {
            if (_myCommand == null)  //set break point here for debug
            {
                _myCommand = new RelayCommand(() =>
                {
                    try
                    {
                       //....
                    }
                    catch (Exception ex)
                    {
                        // notify user if there is any error
                        //....
                    }
                }
                , () => true);
            }
            return _myCommand;
        }
    }

then in xaml, just bind this Command property to a button like:

 <Button Grid.Column="1"  x:Name="Test" Content="Test" Margin="2,0,2,0" Command="{Binding Path=MyCommand}" />

Then run the app, and click on the button, there is no response at all. No error. VM is working fine. The data has been loaded to a datagrid before I click on the Test button.

If debug the app and put break point, the point is never reached.

How to resolve this problem?

4

4 Answers

2
votes

Add a setter to your MyCommand property.

As always, check the Output window for any data binding errors when the XAML is rendered.

Also, try adding a test value converter and putting a breakpoint in the convert method to see if data binding is even being executed on that command. If the breakpoint isn't hit, you know you have a problem in your XAML. If the breakpoint is hit, take a look at the value to see if the data context is correct.

<UserControl.Resources>
    <ResourceDictionary>
        <TestConverter x:Key="TestConverter" />
    </ResourceDictionary>
    <Button Grid.Column="1" x:Name="Test" Content="Test" Margin="2,0,2,0" Command="{Binding Path=MyCommand, Converter={StaticResource TestConverter}}" />
</UserControl>

Test value converter - very useful for debugging data binding issues.

public class TestConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        Debug.WriteLine("TestConverter.Convert(value := {0}, targetType := {1}, parameter := {2}, culture := {3})",
            value, targetType, parameter, culture);
        return value; // put break point here to test data binding
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        Debug.WriteLine("TestConverter.ConvertBack(value := {0}, targetType := {1}, parameter := {2}, culture := {3})",
            value, targetType, parameter, culture);
        return value;
    }
}
2
votes

Works on my machine :)

Seriously, I made a simple project, created a ViewModel, pasted in your code, and it worked. I am guessing you are dealing with some other issue.

Here is my C# code.

Here is my XAML code.

Time to evangelize a bit

This ViewModel code reeks. You might consider using some sort MVVM framework or helpers. If you look at ViewModelSupport, for instance, you can write your ViewModel like this:

public class MyViewModel : ViewModelBase
{
    public void Execute_MyCommand()
    {
        // Your execution code here
    }
}

Then, you avoid all that messy plumbing. Just think about it :)

0
votes

the code looks fine. so you just have to check the output window for databinding errors. maybe you did not set the datacontext of the view correct. btw you should add your breakpoint in the try-catch of the command.

0
votes

1) Make sure you're returning true from the relay command's CanExecute delegate. (I see you are doing this but good to double check).

2) Is the button inside a ListBox, DataGrid or DataForm?

For a ListBox or DataGrid:

If so you need to modify your binding expression to refer to the VM DataContext as opposed to the databound item. See this answer.

For a DataForm :

More tricky, but look at this question.