0

I've a DataGrid and it has a DataGridCheckBox column. And I need to present the check box like this in all the rows of DataGrid:

enter image description here

And following is the XAML and corresponding code I've:

<!--MainWindow.xaml-->
<Window x:Class="DataGridColIssue.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"
        Loaded="Window_Loaded">

    <Window.Resources>
        <Style x:Key="RowNumberCheckBox" TargetType="CheckBox" BasedOn="{StaticResource {x:Type CheckBox}}">
            <Setter Property="FlowDirection" Value="RightToLeft"/>
            <Setter Property="VerticalAlignment" Value="Center"/>
            <Setter Property="HorizontalAlignment" Value="Center"/>
            <Setter Property="Content">
                <Setter.Value>
                    <Grid FlowDirection="LeftToRight">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="20"/>
                            <ColumnDefinition Width="5"/>
                        </Grid.ColumnDefinitions>
                        <TextBlock Grid.Column="0" Text="{Binding Number, StringFormat={}{0:00}}"/>
                    </Grid>
                </Setter.Value>
            </Setter>
            <Setter Property="HorizontalContentAlignment" Value="Center"/>
            <Setter Property="VerticalContentAlignment" Value="Center"/>
        </Style>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="30"/>
        </Grid.RowDefinitions>
        <DataGrid Grid.Row="0"
            Name="DataGridTesting"
                  AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridCheckBoxColumn Header="#"
                                        Binding="{Binding Exclude, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"
                                        ElementStyle="{StaticResource RowNumberCheckBox}"
                                        EditingElementStyle="{StaticResource RowNumberCheckBox}">
                </DataGridCheckBoxColumn>
            </DataGrid.Columns>
        </DataGrid>
        <Button Grid.Row="1"
                Name="AddItems"
                Content="Add Item"
                Click="AddItems_Click"/>
    </Grid>
</Window>

Code

//MainWindow.xaml.cs
using System.Collections.Generic;
using System.Windows;

namespace DataGridColIssue
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public int CurrentOperation;
        public List<Operation> Operations;
        public MainWindow()
        {
            InitializeComponent();
            Operations = new List<Operation>();
            CurrentOperation = 0;
        }

        private void AddItems_Click(object sender, RoutedEventArgs e)
        {
            CurrentOperation++;
            Operations.Add(new Operation(CurrentOperation));
            DataGridTesting.Items.Refresh();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
           DataGridTesting.ItemsSource = Operations;
           DataGridTesting.Items.Refresh();
        }
    }
}

Operation class

namespace DataGridColIssue
{
    public class Operation
    {
        public bool Exclude { get; set; }
        public int Number { get; set; }

        public Operation(int Number)
        {
            this.Number = Number;
        }
    }
}

The issue I've is only the last add row is presented with the text before the CheckBox and it looks like this:

enter image description here

How can I get all the rows to display the number as well before the check box?

ASh
  • 34,632
  • 9
  • 60
  • 82
Abbas
  • 3,872
  • 6
  • 36
  • 63

2 Answers2

1

Grid instance used as Content is shared by all checkBoxes. But it can't have more than one parent so it is diplayed in the last checkBox.

a correct way would be to set ContentTemplate (modified example from this question: Text on the left side of checkbox in WPF?, answer of nmclean)

<Style x:Key="RowNumberCheckBox" TargetType="CheckBox" 
        BasedOn="{StaticResource {x:Type CheckBox}}">
    <Setter Property="Content" Value="{Binding Number}"/>
    <Setter Property="ContentStringFormat" Value="00"/>
    <Setter Property="FlowDirection" Value="RightToLeft" />
    <Setter Property="ContentTemplate">
        <Setter.Value>
            <DataTemplate>
                <ContentControl Content="{Binding}" 
                                ContentStringFormat="{TemplateBinding ContentStringFormat}" />
            </DataTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="HorizontalContentAlignment" Value="Center"/>
    <Setter Property="VerticalContentAlignment" Value="Center"/>
    <Setter Property="HorizontalAlignment" Value="Center"/>
    <Setter Property="VerticalAlignment" Value="Center"/>
</Style>

also did you notice that check mark is flipped when FlowDirection is RightToLeft and CheckBox is checked?

my preferred solution for the given requirement would be DataGridTemplateColumn instead of DataGridCheckBoxColumn or maybe a custom RowHeaderTemplate with text and checkBox.

Community
  • 1
  • 1
ASh
  • 34,632
  • 9
  • 60
  • 82
0

Following the solution provided by @Ash, made the Grid as part of the ContentTemplate and then set the content value, this made the Grid instance to be created for each row, here is the solution that produces desired result:

    <Style x:Key="RowNumberCheckBox" TargetType="CheckBox" BasedOn="{StaticResource {x:Type CheckBox}}">
        <Setter Property="FlowDirection" Value="RightToLeft"/>
        <Setter Property="VerticalAlignment" Value="Center"/>
        <Setter Property="HorizontalAlignment" Value="Center"/>
        <Setter Property="Margin" Value="5"/>
        <Setter Property="ContentTemplate">
            <Setter.Value>
                <DataTemplate>
                    <Grid FlowDirection="LeftToRight">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="20"/>
                            <ColumnDefinition Width="5"/>
                        </Grid.ColumnDefinitions>
                        <TextBlock Grid.Column="0" 
                                   Text="{Binding}"
                                   HorizontalAlignment="Right"/>
                    </Grid>
                </DataTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="Content" Value="{Binding Number}"/>
        <Setter Property="HorizontalContentAlignment" Value="Center"/>
        <Setter Property="VerticalContentAlignment" Value="Center"/>
    </Style>

enter image description here

Community
  • 1
  • 1
Abbas
  • 3,872
  • 6
  • 36
  • 63