Search code examples
wpfwpfdatagrid

Enable button when checkbox is checked in WPF datagrid


I have a Datagrid in WPF in which first column has checkbox column and last column has buttons. Initially, I want to make all the buttons disabled and whenever any checkbox is checked then button of that row should get enabled. checkbox is unchecked then button should be disabled.

Searched a Lot but could not find anything related to this.

I am not using MVVM.. How to do this on the code behind?

Thanks

This is my Xaml Code and I am simply assigning my itemsource on the code behind

            <Grid Grid.Row="2" Grid.ColumnSpan="2" Margin="5" VerticalAlignment="Top" HorizontalAlignment="Center" >
            <Border BorderThickness="0" Margin="10" CornerRadius="15">
                <Border.BitmapEffect>
                    <DropShadowBitmapEffect />
                </Border.BitmapEffect>
                <Grid>
                    <Border x:Name="BDRounded" BorderThickness="0" CornerRadius="15" Background="White"/>
                    <DataGrid HorizontalAlignment="Left" x:Name="dgrdActors" RowHeight="74" AutoGenerateColumns="False" CanUserAddRows="False"
                                      BorderThickness="1,0,0,0" BorderBrush="#FFD1A251" FontSize="28" Foreground="#DCA566" FontFamily="Helvetica Neue" 
                                      CanUserResizeRows="False" AlternatingRowBackground="Linen" AlternationCount="2" Background="#DCA566"
                                      RowHeaderWidth="0" CanUserResizeColumns="False" CanUserSortColumns="False" CanUserReorderColumns="False"
                                      ScrollViewer.CanContentScroll="True" ScrollViewer.VerticalScrollBarVisibility="Visible" 
                                      HorizontalGridLinesBrush="#FFD1A251" VerticalGridLinesBrush="#FFD1A251" Height="326"
                                      SelectionMode="Extended" SelectionUnit="FullRow" VirtualizingStackPanel.VirtualizationMode="Standard"
                                      Style="{StaticResource DatagridStyle}">
                        <DataGrid.Columns>
                            <DataGridTemplateColumn Width="70" CanUserReorder="False" CanUserResize="False" CanUserSort="False" CellStyle="{StaticResource                      HitVisibilityCellStyle}" HeaderStyle="{StaticResource HeaderStyle}" >
                                <DataGridTemplateColumn.CellTemplate>
                                    <DataTemplate>
                                        <Viewbox Margin="-1">
                                            <!--<CheckBox x:Name="chkboxactors" HorizontalAlignment="Center" VerticalAlignment="Center" 
                                                      IsChecked="{Binding IsActorChecked, UpdateSourceTrigger=PropertyChanged}"></CheckBox>-->
                                            <CheckBox x:Name="chkboxActors" HorizontalAlignment="Center" VerticalAlignment="Center"></CheckBox>
                                        </Viewbox>
                                    </DataTemplate>
                                </DataGridTemplateColumn.CellTemplate>
                            </DataGridTemplateColumn>
                            <DataGridTextColumn Header="Actor Name(s)" Width="300" Binding="{Binding ActorName}" CanUserReorder="False" CellStyle="{StaticResource                              CellStyle}" CanUserResize="False" CanUserSort="False" HeaderStyle="{StaticResource HeaderStyle}"                            IsReadOnly="True">
                                <DataGridTextColumn.ElementStyle>
                                    <Style TargetType="TextBlock">
                                        <Setter Property="TextWrapping" Value="Wrap"/>
                                        <Setter Property="HorizontalAlignment" Value="Center"></Setter>
                                        <Setter Property="VerticalAlignment" Value="Center"></Setter>
                                    </Style>
                                </DataGridTextColumn.ElementStyle>
                            </DataGridTextColumn>
                            <DataGridTextColumn Header="Role(s)" Width="300" Binding="{Binding Role}" CanUserReorder="False" CellStyle="{StaticResource CellStyle}"                     CanUserResize="False" CanUserSort="False" HeaderStyle="{StaticResource HeaderStyle}" IsReadOnly="True">
                                <DataGridTextColumn.ElementStyle>
                                    <Style TargetType="TextBlock">
                                        <Setter Property="TextWrapping" Value="Wrap"/>
                                        <Setter Property="HorizontalAlignment" Value="Center"></Setter>
                                        <Setter Property="VerticalAlignment" Value="Center"></Setter>
                                    </Style>
                                </DataGridTextColumn.ElementStyle>
                            </DataGridTextColumn>
                            <DataGridTemplateColumn Width="250" CanUserReorder="False" CanUserResize="False" HeaderStyle="{StaticResource HeaderStyle}"                         CellStyle="{StaticResource HitVisibilityCellStyle}">
                                <DataGridTemplateColumn.CellTemplate>
                                    <DataTemplate>
                                        <Button x:Name="btnSelectRole" Content="Select Role" Style="{StaticResource DatagridButtonStyle}"></Button>
                                    </DataTemplate>
                                </DataGridTemplateColumn.CellTemplate>
                            </DataGridTemplateColumn>
                        </DataGrid.Columns>

                        <DataGrid.OpacityMask>
                            <VisualBrush Visual="{Binding ElementName=BDRounded}"/>
                        </DataGrid.OpacityMask>
                    </DataGrid>
                </Grid>
            </Border>
        </Grid>

Solution

  • Here you go!

    There's no need to do the enabling/disabling in the ViewModel, as this can all be done in XAML.

    XAML:

    <DataGrid ItemsSource="{Binding Items}" AutoGenerateColumns="False">
        <DataGrid.Columns>
            <DataGridCheckBoxColumn Binding="{Binding IsChecked, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />
            <DataGridTemplateColumn>
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Button Width="100">
                            <Button.Style>
                                <Style TargetType="Button">
                                    <Setter Property="IsEnabled" Value="false"/>
                                    <Style.Triggers>
                                        <DataTrigger Binding="{Binding IsChecked}" Value="true">
                                            <Setter Property="IsEnabled" Value="True"/>
                                        </DataTrigger>
                                    </Style.Triggers>
                                </Style>
                            </Button.Style>
                        </Button>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>
    

    ViewModel:

    public class ViewModel
    {
        public List<Data> Items { get; private set; }
        public ViewModel()
        {
            Items = new List<Data>
            {
                new Data(),
                new Data(),
                new Data()
            };
        }
    }
    
    public class Data : INotifyPropertyChanged
    {
        private bool _isChecked;
        public bool IsChecked 
        { 
            get  {return _isChecked; }
            set 
            {
                _isChecked = value;
                OnPropertyChanged("IsChecked");               
            }
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string property)
        {
            var handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(property));
            }
        }
    }
    

    Edit: Since you've requested a code-behind implementation, here you go. This works by traversing the visual tree based on the current row that the checkbox was clicked from.

    XAML:

    <Window x:Class="WpfApplication1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <DataGrid AutoGenerateColumns="False" x:Name="MyDataGrid">
            <DataGrid.Columns>
                <DataGridTemplateColumn>
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <CheckBox Click="CheckBox_Clicked"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTemplateColumn>
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Button Width="100" x:Name="Button" IsEnabled="false" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Window>
    

    XAML.CS:

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            MyDataGrid.ItemsSource = new List<string>
            {
                "test",
                "test1",
                "test2",
                "test3"
            };
        }
    
        private void CheckBox_Clicked(object sender, RoutedEventArgs e)
        {
            var checkBox = sender as CheckBox;
            if (checkBox != null)
            {
                var associatedRow = VisualTreeHelper.GetParent(checkBox);
    
                while ((associatedRow != null) && (associatedRow.GetType() != typeof(DataGridRow)))
                {
                    associatedRow = VisualTreeHelper.GetParent(associatedRow);
                }
    
                var dataGridRow = associatedRow as DataGridRow;
                if (dataGridRow != null)
                {
                    var associatedButton = FindChild(dataGridRow, "Button");
                    if (associatedButton != null)
                    {
                        associatedButton.IsEnabled = checkBox.IsChecked.HasValue ? checkBox.IsChecked.Value : false;
                    }
                }
            }
        }
    
        public static Button FindChild(DependencyObject parent, string childName)
        {
            if (parent == null) return null;
    
            Button foundChild = null;
    
            var childrenCount = VisualTreeHelper.GetChildrenCount(parent);
            for (var i = 0; i < childrenCount; i++)
            {
                var child = VisualTreeHelper.GetChild(parent, i);
                var childType = child is Button;
                if (!childType)
                {
                    foundChild = FindChild(child, childName);
                    if (foundChild != null) break;
                }
                else if (!string.IsNullOrEmpty(childName))
                {
                    var frameworkElement = child as FrameworkElement;
                    if (frameworkElement != null && frameworkElement.Name == childName)
                    {
                        foundChild = (Button)child;
                        break;
                    }
                }
                else
                {
                    foundChild = (Button)child;
                    break;
                }
            }
            return foundChild;
        }
    }