0

My DataTable contains values of composite types for each column, the goal is for use both to dispaly the Value Property and style it by State Property

public class PairData
{
    public string Value { get; set; }
    public int State { get; set; }
}

it is possible to config the datagrid menualy like:

        <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding Path=Column1.Value}">
                <DataGridTextColumn.ElementStyle>
                    <Style TargetType="{x:Type TextBlock}">
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding Path=Column1.State}" Value="1">
                                <Setter Property="Background" Value="Red"/>
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </DataGridTextColumn.ElementStyle>
            </DataGridTextColumn>
        </DataGrid.Columns>

but i want to generate columns dinmicly using AutoGenerateColumns="True"

Is there a way to bind all columns for 'Value' Property? Perhaps something like:

      <DataGrid  ItemsSource="{Binding Path=Source}" >
        <DataGrid.CellStyle>
            <Style TargetType="DataGridCell">
                <Setter Property="Foreground" Value="Black" />
                <Setter Property="TextBlock.Text" Value="{Binding Value}"/>
            </Style>
        </DataGrid.CellStyle>
    </DataGrid>

I got an error:

System.Windows.Data Error: 40 : BindingExpression path error: 'Value' property not found on 'object' ''DataRowView' (HashCode=15375790)'. BindingExpression:Path=Value; DataItem='DataRowView' (HashCode=15375790); target element is 'DataGridCell' (Name=''); target property is 'Text' (type 'String')
mordechai
  • 829
  • 1
  • 7
  • 23

2 Answers2

0

You should replace the DataTable with an IEnumerable<PairData> implementation (like for example a List<PairData>).

You can't really store a custom object like PairData in a DataRow of a DataTable:

Binding an object to data grid cell - conditional cell style

mm8
  • 163,881
  • 10
  • 57
  • 88
  • `PairData` is not instead of `DataRow` ,is instead of cell value, all Column Type of `DataTable` are from `PairData` – mordechai Dec 17 '19 at 08:03
  • @mordechai: Didn't you read my answer? You cannot store custom objects in a `DataTable` so you shouldn't use one. – mm8 Dec 18 '19 at 10:06
  • why not, i do it, i have converted my `DataTable` to new` DataTable` with other columns type – mordechai Dec 19 '19 at 00:24
  • Maybe you should show *how* you have done this because you cannot solve your issue using a `DataTable` with custom objects in it. – mm8 Dec 19 '19 at 14:33
  • i can't do it here , because the question is closed, and the answer is too long... – mordechai Dec 21 '19 at 21:45
  • @mordechai: Edit the question. – mm8 Dec 30 '19 at 12:20
0

this is the solution:

public abstract class StateExtension
{
    public abstract void SetValues(object value, Brush state);
}
public class StateExtension<T> : StateExtension
{

    public override void SetValues(object value, Brush state)
    {
        if (!(value is System.DBNull))
            Value = (T)value;
        State = state;
    }
    public T Value { get; set; }
    public Brush State { get; set; }
}

public static class DataTableEx
{
    public static DataTable ToDataTableEX(this DataTable dataTable)
    {

        var tb = new DataTable();
        Dictionary<int, Type> types = new Dictionary<int, Type>();
        var columnsCount = dataTable.Columns.Count;
        foreach (DataColumn column in dataTable.Columns)
        {
            var type = typeof(StateExtension<>).MakeGenericType(column.DataType);
            tb.Columns.Add(column.ColumnName, type);
            types.Add(column.Ordinal, type);
        }
        Type currentType = null;int x = 0;
        foreach (DataRow item in dataTable.Rows)
        {

            var values = new object[columnsCount];
            for (var i = 0; i < columnsCount; i++)
            {
                currentType = types[i];
                StateExtension instance = Activator.CreateInstance(currentType) as StateExtension;
                Brush state = GetStateBrush(item,x++);

                instance.SetValues(item[i], state);
                values[i] = instance;
            }

            tb.Rows.Add(values);
        }

        return tb;
    }

    private static Brush GetStateBrush(DataRow item,int i)
    {
        switch (i%3)
        {
            case 2:
                return LightGreen;
            case 1:
                return LightBlue;
            case 0:
            default:
                return LightGreen;
        }
    }
    static Brush LightPink = (Brush)new BrushConverter().ConvertFrom("LightPink");
    static Brush LightGreen = (Brush)new BrushConverter().ConvertFrom("LightGreen");
    static Brush LightBlue = (Brush)new BrushConverter().ConvertFrom("LightBlue");

}
public class DataGridBehavior : Behavior<DataGrid>
{



    protected override void OnAttached()
    {
         this.AssociatedObject.AutoGeneratingColumn += AssociatedObject_AutoGeneratingColumn;
    }


    private void AssociatedObject_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
    {
        try
        {
             if (e.PropertyType.IsSubclassOf(typeof(StateExtension)))
            {
                var binding = ((Binding)((DataGridTextColumn)e.Column).Binding);
                 binding.Path.Path = e.PropertyName + ".Value";
                Style cellStyle = new Style(typeof(DataGridCell));
                Setter backgroundSetter = new Setter(DataGridCell.BackgroundProperty, new Binding(e.PropertyName + ".State"));
                cellStyle.Setters.Add(backgroundSetter);
                ((DataGridTextColumn)e.Column).CellStyle = cellStyle;
            }
        }
        catch (Exception ex)
        {
             return;
        }
    }
 }

and xaml section is :

<DataGrid >
    <i:Interaction.Behaviors>
        <uiModel:DataGridBehavior  />
    </i:Interaction.Behaviors>
</DataGrid>

when i: is

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
mordechai
  • 829
  • 1
  • 7
  • 23