WPF使用代码隐藏在DataGrid或GridView中自定义单元格外观

时间:2011-07-13 14:05:04

标签: wpf gridview datagrid cell

我正在开发一个需要提供只读数据列表的应用程序,在这种情况下是各种巡逻单元的当前状态。我已经为此尝试了DataGrid和GridView,并且尚未做出最终选择。基本上它将归结为最少的障碍。

填充到网格中的数据最终将以平面文件的形式出现,该文件将被解析并组装成DataTable或某种形式的集合,我将绑定到网格。为了测试,我只是将一个示例DataSet绑定到网格。

根据不同单元格中的值,我需要更改包含数据的单元格的外观。例如,如果列中的任何单元格"优先级"价值低于" 5"将背景更改为红色或列中的任何单元格"键入"具有" FIELD"的价值将背景更改为绿色。

特定条件格式将仅适用于已定义列中的所有单元格。特定列可能会应用多个条件格式。

我希望能够使用标准的DataGrid或GridView控件,因为它们包含在WPF中。我正在使用Visual Studio 2010。


我遇到的最大障碍是在开发时不知道将要应用的条件格式。这是可由用户配置的内容。将有一个XML文件将在其中定义所有条件格式。

我见过的任何一些似乎对我不起作用的例子都使用具有硬编码条件格式属性的转换器。我需要完全动态地做到这一点。如果可能的话,我更喜欢使用代码。

非常感谢任何帮助。


更新

我已经为我原来的问题开发了一个解决方案。这就是我所做的。

        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);
        }

然后在CreateDataGridColumn中我有。

    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();
        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;
    }

所以,这确实令我感到非常需要,而且已经过彻底的测试。如果有人对如何优化以获得更好的性能或减少代码有任何想法,我会很感激反馈。

现在我遇到了一个新问题。

请记住它必须是动态的,如何将其扩展为接受多个条件?例如,如果" Type"是" PT"或"类型是" FT"将背景设置为黑色或者如果"键入"是" PS"和"优先级"是" 10"将背景设置为蓝色。

除此之外,我如何将格式条件应用于整行?

1 个答案:

答案 0 :(得分:2)

我创建了一个样本.... Xaml代码......

 <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>

代码背后......

          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看起来像这样......

enter image description here