0
votes

I'm creating a two data tables dynamically in my view model. before I'm displaying them in my view i'm comparing each cell value in one DataTable to the same cell in the second DataTable . My problem is that I want to provide the different cells different background color. How can I do it programtically ?

Here is the first DataGrid:

 <GroupBox Header="Xml 1 Details" Margin="10,10,10,10" Grid.Row="1" Grid.ColumnSpan="4" Grid.Column="0">
        <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>

                <GroupBox x:Name="GridGroupBox"
                  Grid.Column="0"
                  Header="{Binding TableName}">
                    <DataGrid x:Name="DataGrid" Margin="5,5,5,5"
                      ItemsSource="{Binding GenericDataTable}"
                      attachedBehaviors:DataGridColumnsBehavior.BindableColumns="{Binding GridColumns}"                                 
                      AutoGenerateColumns="False"
                      EnableRowVirtualization="False">                            
                    </DataGrid>
                </GroupBox>
            </Grid>
        </ScrollViewer>
    </GroupBox>

Second DataGrid:

    <GroupBox Header="Xml 2 Details" Margin="10,20,10,10" Grid.Row="2" Grid.ColumnSpan="4" Grid.Column="0">
        <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>


                <GroupBox x:Name="GridGroupBox2" 
                Grid.Column="0"
                Header="{Binding TableName}">

                    <DataGrid x:Name="DataGrid2" Margin="5,5,5,5" 
                    ItemsSource="{Binding GenericDataTable2}"
                    attachedBehaviors:DataGridColumnsBehavior.BindableColumns="{Binding GridColumns2}"                                 
                    AutoGenerateColumns="False"
                    EnableRowVirtualization="False"
                    />                    
                </GroupBox>
            </Grid>
        </ScrollViewer>
    </GroupBox>

Creating them programatically:

    private void GenerateFirstXmlDynamicColumns(DataTable dt, List<string> cols)
    {

        GridColumns = new ObservableCollection<DataGridColumn>();

        foreach (DataColumn col in dt.Columns)
        {

            GridColumns.Add(new DataGridTextColumn
            {
                Header = col.ColumnName,
                Binding = new Binding(col.ColumnName)
            });
        }

        RaisePropertyChanged("GridColumns");
        GenericDataTable = dt;
        RaisePropertyChanged("GenericDataTable");
    }

    private void GenerateSecondXmlDynamicColumns(DataTable dt, List<string> cols)
    {
        GridColumns2 = new ObservableCollection<DataGridColumn>();

        foreach (DataColumn col in dt.Columns)
        {

            GridColumns2.Add(new DataGridTextColumn
            {
                Header = col.ColumnName,
                Binding = new Binding(col.ColumnName)
            });
        }

        RaisePropertyChanged("GridColumns2");
        GenericDataTable2 = dt;
        RaisePropertyChanged("GenericDataTable2");
    }

Here I'm comparing the cells and I want to change the background color of the different cells:

private void CompareData()
    {
        for (int i = 0; i < GenericDataTable.Rows.Count; i++)
        {
            for (int j = 0; j < GenericDataTable.Columns.Count; j++)
            {
                if (!GenericDataTable.Rows[i][j].Equals(GenericDataTable2.Rows[i][j]))//if cells are different
                {

                }
            }

        }     
    }
2
The way to get help here is to try first, show your code and then people are happy to help. - kenny

2 Answers

0
votes

To get DataGrid cell from indexes:

public DataGridCell GetCell(DataGrid dg, int row, int column)
    {
        DataGridRow rowContainer = GetRow(dg, row);
        if (rowContainer != null)
        {
            DataGridCellsPresenter presenter = GetVisualChild<DataGridCellsPresenter>(rowContainer);
            if (presenter == null)
            {
                dg.ScrollIntoView(rowContainer, dg.Columns[column]);
                presenter = GetVisualChild<DataGridCellsPresenter>(rowContainer);
            }
            DataGridCell cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(column);
            return cell;
        }
        return null;
    }

    public static DataGridRow GetRow(DataGrid dg, int index)
    {
        DataGridRow row = (DataGridRow)dg.ItemContainerGenerator.ContainerFromIndex(index);
        if (row == null)
        {
            dg.UpdateLayout();
            dg.ScrollIntoView(dg.Items[index]);
            row = (DataGridRow)dg.ItemContainerGenerator.ContainerFromIndex(index);
        }
        return row;
    }

    public static T GetVisualChild<T>(Visual parent) where T : Visual
    {
        if (parent == null) return null;
        T child = default(T);
        int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
        for (int i = 0; i < numVisuals; i++)
        {
            Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
            child = v as T;
            if (child == null)
            {
                child = GetVisualChild<T>(v);
            }
            if (child != null)
            {
                break;
            }
        }
        return child;
    }

And set background:

var cell = GetCell(DataGrid2, i, j);
cell.Background = color;
0
votes

Here is the solution :

 
 Create a MultiConverter:

 public object Convert(object[] values, 
 Type targetType, object parameter,      
 CultureInfo culture)
    {
        var dataContext = values[0];
        var dg = (DataGrid)values[1];
        var i = (DataGridCell)values[2];
        var col = i.Column.DisplayIndex;
        var row = dg.Items.IndexOf(i.DataContext);
        if (row >= 0 && col >= 0)
        {
            DataTable td1 = ((CheckXmlAppWpf.ViewModel.MainWindowViewModel) (dataContext)).GenericDataTable;
            DataTable td2 = ((CheckXmlAppWpf.ViewModel.MainWindowViewModel)(dataContext)).GenericDataTable2;

            if (!td1.Rows[row][col].Equals(td2.Rows[row][col]))
            {
                GetCell(dg, row, col).Background = Brushes.Yellow;
            }
        }

        return SystemColors.AppWorkspaceColor;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new System.NotImplementedException();
    }
}

Use it in the xaml:

<DataGrid x:Name="DataGrid" Margin="5,5,5,5" ItemsSource="{Binding GenericDataTable}" attachedBehaviors:DataGridColumnsBehavior.BindableColumns="{Binding GridColumns}" AutoGenerateColumns="False" EnableRowVirtualization="False"> <DataGrid.Resources> <Style TargetType="DataGridCell"> <Setter Property="Background"> <Setter.Value> <MultiBinding Converter="{StaticResource NameToBrushMultiValueConverter}" > <MultiBinding.Bindings> <Binding RelativeSource="{RelativeSource AncestorType=Window}" Path="DataContext" /> <Binding RelativeSource="{RelativeSource AncestorType=DataGrid}"></Binding> <Binding RelativeSource="{RelativeSource Self}"/> </MultiBinding.Bindings> </MultiBinding> </Setter.Value> </Setter> </Style> </DataGrid.Resources> </DataGrid>