Question

I have this markup

<DataGrid Margin="10,10,10,48" AutoGenerateColumns="False" Name="grdUsers"
          ItemsSource="{Binding Users}"
>
    <DataGrid.Columns>
        <DataGridTextColumn Header="Name" Width="*" Binding="{Binding Name}" />
        <DataGridTextColumn Header="Username" Width="*" Binding="{Binding Username}" />
        <DataGridTextColumn Header="Password" Width="*" Binding="{Binding Password}" />
        <DataGridTextColumn Header="Role" Width="*" Binding="{Binding Path=Role.Name}" />
    </DataGrid.Columns>
</DataGrid>
<Button Content="Add" HorizontalAlignment="Left" Margin="10,0,0,10" Width="75" Height="20" VerticalAlignment="Bottom"/>
<Button Content="Edit" HorizontalAlignment="Left" Margin="90,0,0,10" Width="75" Height="20" VerticalAlignment="Bottom"/>

<Button Content="Remove" Margin="0,0,10,10" Height="20" VerticalAlignment="Bottom" HorizontalAlignment="Right" Width="75"
        Command="{Binding Remove}" CommandParameter="{Binding ElementName=grdUsers, Path=SelectedItem}"/>

My RelayCommand

public class RelayCommand : ICommand
{
    private readonly Action<object> execute = null;
    private readonly Predicate<object> canExecute = null;

    public RelayCommand(Action<object> execute, Predicate<object> canExecute = null)
    {
        this.execute = execute;
        this.canExecute = canExecute;
    }


    #region ICommand members

    public bool CanExecute(object parameter)
    {
        return canExecute == null ? true : canExecute(parameter);
    }

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
        execute(parameter);
    } 

    #endregion
}

My CanExecute method on my RelayCommand returns true if there is a item selected in the DataGrid.

But the Window opens without any items selected, causing the button to be disabled. If I select something on the DataGrid nothing happens.

How can I "refresh" the button if a row has been selected in the DataGrid?

Was it helpful?

Solution 3

I changed the event to

public event EventHandler CanExecuteChanged
{
    add { CommandManager.RequerySuggested += value; }
    remove { CommandManager.RequerySuggested -= value; }
}

And now it is working.

OTHER TIPS

You can create style for Button and using DataTrigger:

<Button Content="Remove" Margin="0,0,10,10" Height="20" VerticalAlignment="Bottom" HorizontalAlignment="Right" Width="75"
    Command="{Binding Remove}" CommandParameter="{Binding ElementName=grdUsers, Path=SelectedItem}">
    <Button.Style>
        <Style TargetType="Button">
            <Setter Property="IsEnabled" Value="True" />
            <Setter Property="Opacity" Value="1" />
            <Style.Triggers>
                <DataTrigger Binding="{Binding ElementName=grdUsers, Path=SelectedItem}" Value="{x:Null}">
                    <Setter Property="IsEnabled" Value="False" />
                    <Setter Property="Opacity" Value=".5" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Button.Style>
</Button>

Seems to me like this could be accomplished by executing the RaiseCanExecuteChanged() method on the command when the selection occurs. There are a number of ways to accomplish this (direct event invocation, IsSelected bindings into your view model that raise the event, Attached Behaviors, etc.) and you would do well to investigate all of them and decide which works best for your scenario.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top