开发者

WPF customizing cell appearance in DataGrid or GridView using code behind

开发者 https://www.devze.com 2023-03-19 19:52 出处:网络
I am developing an application that needs to present a read only list of data, in this case the current status of various patrol units.I have experimented with both the DataGrid and the GridView for t

I am developing an application that needs to present a read only list of data, in this case the current status of various patrol units. I have experimented with both the DataGrid and the GridView for this and have not made a final choice on which to use as of yet. Basically it will come down to whichever one has the fewest roadblocks.

The data being populated to the grid will ultimately come in the form of an flat file that will be parsed and assembled into a DataTable or some form of collection that I will bind to the grid. For testing I am just binding a sample DataSet to the grid.

Based on the value in different cells I need to change the appearance of the cell containing the data. For instance, if any cell in column "Priority" has value less than "5" change background to red or if any cell in column "Type" has value of "FIELD" change background to green.

A particullar conditional formatting will apply to all cells in the defined column only. A particular column may have multiple conditional formatting applied to it.

I would like something that will work with the the standard DataGrid or GridView controls as they are included with WPF. I am using Visual Studio 2010.


A biggest obstacle I have is that the conditional formatting that will be applied is not known at development time. This is something that is configurable by the user. There will be an XML file will all of the conditional formats defined in it.

Any examples I have seen, which don't seem to work for me, use converters with hard coded conditional formatting attributes. I need to do this completely dynamic. I prefer to use code behind if possible.

Any help is greatly appreciated.


Updated

I have developed a solution to my original problem. Here is what I did.

        foreach (ColumnEntity column in ColumnList)
        {
            DataGridTemplateColumn newColumn = CreateDataGridColumn(column, ColumnList.FormatConditionGroups);
            newColumn.Header = column.Header;
            newColumn.Width = new DataGridLength(column.DisplayWidth);
            _dataGrid.Columns.Add(newColumn);
        }

Then in CreateDataGridColumn I have.

    private DataGridTemplateColumn CreateDataGridColumn(ColumnEntity dataColumn, FormatConditionGroup formatConditionGroup)
    {
        DataGridTemplateColumn newColumn = new DataGridTemplateColumn();
        DataTemplate dataTemplate = new DataTemplate();

        String triggerValue;

        // Create the label that will display the cell contents
        FrameworkElementFactory labelFNFactory;
        labelFNFactory = new FrameworkElementFactory(typeof(Label));
        Binding binding = new Binding();
        开发者_StackOverflow社区binding.Path = new PropertyPath(dataColumn.Tag);
        labelFNFactory.SetBinding(Label.ContentProperty, binding);
        labelFNFactory.Name = dataColumn.Name;
        labelFNFactory.SetValue(Label.VerticalContentAlignmentProperty, VerticalAlignment.Center);
        labelFNFactory.SetValue(Label.MarginProperty, new Thickness(-2));
        dataTemplate.VisualTree = labelFNFactory;

        if (formatConditionGroup != null)
        {
            foreach (FormatCondition formatCondition in formatConditionGroup.FormatConditionItems)
            {
                // Check to see if this is the target column for the format condition
                if (formatCondition.GetPropertyValue("Target") == dataColumn.Tag)
                {
                    // Create a data trigger to apply the format condition
                    DataTrigger trigger = new DataTrigger();

                    // Set up the binding to the source column, typically this will be the current column but it could be different
                    trigger.Binding = new Binding { Path = new PropertyPath(formatCondition.Source) };
                    trigger.Value = formatCondition.Value;

                    // Check to see if we need to change the text color
                    if ((triggerValue = formatCondition.TextColor) != null)
                        trigger.Setters.Add(new Setter(Label.ForegroundProperty, new SolidColorBrush((Color)ColorConverter.ConvertFromString(triggerValue)), textBlockName));

                    // Check to see if we need to change the background color
                    if ((triggerValue = formatCondition.BackColor) != null)
                        trigger.Setters.Add(new Setter(Label.BackgroundProperty, new SolidColorBrush((Color)ColorConverter.ConvertFromString(triggerValue)), textBlockName));
                    dataTemplate.Triggers.Add(trigger);
                }
            }
        }

        newColumn.CellTemplate = dataTemplate;

        return newColumn;
    }

So, this does excatly what I need and it has been thoroughly tested. If anyone has ideas on how this could be optimized for better performance or reduced code I'd appreciate the feedback.

Now I have a new problem.

Keeping in mind it has to be dynamic how can this be expanded to accept multiple conditions? For example, if "Type" is "PT" or "Type is "FT" set background to black or if "Type" is "PS" and "Priority" is "10" set background to blue.

Further to this, how could I apply a format condition to the entire row?


i created a sample.... Xaml code...

 <DataGrid Name="myDataGrid" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTemplateColumn Header="Priority" Width="Auto" MinWidth="100" >
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Grid>
                                <Grid.Style>
                                    <Style>
                                        <Style.Triggers>
                                            <DataTrigger Binding="{Binding Type}" Value="FIELD">
                                                <Setter Property="Grid.Background" Value="Red"/>
                                            </DataTrigger>
                                            <DataTrigger Binding="{Binding Type}" Value="NOT A FIELD">
                                                <Setter Property="Grid.Background" Value="Green"/>
                                            </DataTrigger>
                                        </Style.Triggers>
                                    </Style>
                                </Grid.Style>
                                <TextBlock Text="{Binding Type}"></TextBlock>
                            </Grid>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTemplateColumn Header="Type" Width="Auto" MinWidth="100" >
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Grid>
                                <Grid.Style>
                                    <Style>
                                        <Style.Triggers>
                                            <DataTrigger Binding="{Binding Priority}" Value="1">
                                                <Setter Property="Grid.Background" Value="Red"/>
                                            </DataTrigger>
                                            <DataTrigger Binding="{Binding Priority}" Value="2">
                                                <Setter Property="Grid.Background" Value="Green"/>
                                            </DataTrigger>
                                            <DataTrigger Binding="{Binding Priority}" Value="3">
                                                <Setter Property="Grid.Background" Value="Blue"/>
                                            </DataTrigger>
                                            <DataTrigger Binding="{Binding Priority}" Value="4">
                                                <Setter Property="Grid.Background" Value="Yellow"/>
                                            </DataTrigger>
                                            <DataTrigger Binding="{Binding Priority}" Value="0">
                                                <Setter Property="Grid.Background" Value="Orange"/>
                                            </DataTrigger>
                                        </Style.Triggers>
                                    </Style>
                                </Grid.Style>

                                <TextBlock Text="{Binding Priority}">
                                </TextBlock>
                            </Grid>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>

Code behind...

          List<Temp> items = new List<Temp>();
            Random rand = new Random();
            for (int i = 0; i < 20; i++)
            {
                items.Add(new Temp { Priority = rand.Next(0, 5), Type = i % 2 == 0 ? "FIELD" : "NOT A FIELD" });
            }
            myDataGrid.ItemsSource = items;


 public class Temp
        {
            public string Type { get; set; }
            public int Priority { get; set; }

        }

out put looks like this......

WPF customizing cell appearance in DataGrid or GridView using code behind

0

精彩评论

暂无评论...
验证码 换一张
取 消