Search code examples
c#wpfwpfdatagrid

How to enable a specific button on a specific row of a datagrid


I would to like to enable a Button for a specific row of a DataGrid and disable it for the other rows in code behind. The thing is the IsEnabled property impact all the buttons in all the rows which is not what I want. It cannot have two different values (visible for some rows and Collapsed for others in the same time)

Can you help me please ?

here is my xaml :

<DataGrid ItemsSource="{Binding TaskUsers}" Name="DgUser" AutoGenerateColumns="False"  IsReadOnly="True" SelectionUnit="FullRow" SelectionMode="Single" CanUserAddRows="False" CanUserSortColumns="False" SelectedValuePath="TaskUserId" >
   <DataGrid.Columns>
       <DataGridTemplateColumn>
             <DataGridTemplateColumn.HeaderTemplate>
                   <DataTemplate>
                        <Button  BorderThickness="0" ToolTip="Subscribe" Click="AddTaskUser_OnClick">
                            <Image Source="/Sinergi;component/Images/add-icon16.png"/>
                        </Button>
                   </DataTemplate>
             </DataGridTemplateColumn.HeaderTemplate>
             <DataGridTemplateColumn.CellTemplate>
                   <DataTemplate>
                        <Button BorderThickness="0" ToolTip="Delete a User" Click="DeleteTaskUser_OnClick" Name="DeleteUserButton" Loaded="DeleteUserButton_OnLoaded">
                              <Image Source="/Sinergi;component/Images/Trash-can-icon16.png" />
                        </Button>
                   </DataTemplate>
             </DataGridTemplateColumn.CellTemplate>
      </DataGridTemplateColumn>

      <DataGridTextColumn Header="UserName" Binding="{Binding User.Name}"  />
  </DataGrid.Columns>

here is my code behind code

private void DeleteUserButton_OnLoaded(object sender, RoutedEventArgs e)
    {
        var delete = sender as Button;
        if (delete == null) return;
        foreach (var item in DgUser.Items)
        {
            var o = (TaskUser) item;
            if (o.UserId == Identity.This.OnBehalfOfUser.UserId) continue;
            delete.IsEnabled = false;
            delete.Visibility = Visibility.Collapsed;
        }
    }

Solution

  • You should bind the IsEnabled property of the Button to a property of your TaskUser object and get rid of the DeleteUserButton_OnLoaded event handler:

    <DataTemplate>
        <Button BorderThickness="0" ToolTip="Delete a User" Click="DeleteTaskUser_OnClick" Name="DeleteUserButton">
            <Button.Style>
                <Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding UserId}" Value="{x:Static local:Identity.This.OnBehalfOfUser.UserId}">
                            <Setter Property="IsEnabled" Value="False" />
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </Button.Style>
            <Button.Content>
                <Image Source="/Sinergi;component/Images/Trash-can-icon16.png" />
            </Button.Content>
        </Button>
    </DataTemplate>
    

    You need to set the Value of the DataTrigger to whatever Identity.This.OnBehalfOfUser.UserId is, or use a value converter:

    <DataTemplate>
        <DataTemplate.Resources>
            <local:Converter x:Key="converter" />
        </DataTemplate.Resources>
        <Button BorderThickness="0" ToolTip="Delete a User" Click="DeleteTaskUser_OnClick" Name="DeleteUserButton">
            <Button.Style>
                <Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding UserId, Converter={StaticResource converter}}" Value="False">
                            <Setter Property="IsEnabled" Value="False" />
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </Button.Style>
            <Button.Content>
                <Image Source="/Sinergi;component/Images/Trash-can-icon16.png" />
            </Button.Content>
        </Button>
    </DataTemplate>
    

    Converter:

    class Converter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return (int)value == Identity.This.OnBehalfOfUser.UserId;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotSupportedException();
        }
    }