【问题标题】:How to set datagrid row's background based on variably value in cell如何根据单元格中的变量值设置数据网格行背景
【发布时间】:2017-02-05 00:14:16
【问题描述】:

我目前正在使用 C# WPF DataGrid
DataGrid 使用我的数据库作为 ItemsSource,我使用 DataGrid 列出我的订单。
例如:

大汉堡 1
大 MAC 1
芝士汉堡 1

MCNUGGETS 2
鸡 2
可口可乐 2
百事可乐 2

如您所见,我列出了每个订单的商品,每个商品旁边都有数字 1 或数字 2。这些数字帮助我确定哪些商品属于哪个订单。强>

我的问题是如何绘制每一行,哪些商品属于特定订单,例如当商品与订单 1 相关联时为红色,当商品与订单 2 相关联时为蓝色,依此类推。或者,作为替代方案,仅绘制每个订单的最后一行(请看下面的粗体部分)。

我需要以某种方式将它们分开,因为当我将它们加载到数据网格时,它看起来很乱。

想象一下:

大汉堡 1 BIG MAC 1
芝士汉堡 1
麦克努吉斯 2
鸡 2
可口可乐 2
百事可乐 2
大汉堡 3
巨无霸 3
芝士汉堡 3
MCNUGGETS 3
鸡 4
可口可乐 4
百事可乐 4

看起来很乱..

(正如我之前所说,如果不可能整行,是否可以仅绘制每个订单的最后一行,只是为了在屏幕上创建可见的分隔。)

这是我到目前为止所拥有的,但这不是最佳的,因为它使用硬编码值:

 <DataGrid.RowStyle>
        <Style TargetType="DataGridRow"> 
            <Style.Triggers>
                <DataTrigger Binding="{Binding NumberOfOrder}"  Value="1">
                    <Setter Property="Background" Value="Red"></Setter>
                </DataTrigger>
                <DataTrigger Binding="{Binding NumberOfOrder}"  Value="2">
                    <Setter Property="Background" Value="Green"></Setter>
                </DataTrigger>
                <DataTrigger Binding="{Binding NumberOfOrder}"  Value="3">
                    <Setter Property="Background" Value="Orange"></Setter>
                </DataTrigger>
            </Style.Triggers>
        </Style>
</DataGrid.RowStyle>

代码隐藏:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        try
        {
            InitializeComponent();
            this.WindowStartupLocation = WindowStartupLocation.CenterScreen;
            this.WindowState = WindowState.Maximized;

            datagrid1.ItemsSource = OrdersController.localOrders();
        }
        catch(Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }
}

在这里你可以看到我正在使用硬编码值,以防我的 NumberOfOrder 是 1,2 或 3 下一步: 绘制行,这是不是很好的解决方案,因为NumberOfOrder 会有很多不同的值。

在 Mat 回答后编辑:

public MainWindow()
{
InitializeComponent();

    CollectionViewSource collectionViewSource = new CollectionViewSource();

    var ordersList = OrdersController.localOrders(); //ORDERS LIST

    collectionViewSource.Source = new List<OrdersController.OrdersLocal>()
    {
        foreach(var item in ordersList) 
        {
            new OrdersController.OrdersLocal() {Title = item.Title, NumberOfOrder = item.NumberOfOrder, Desc = item.Desc,   User = item.User }
        }

    };

    collectionViewSource.GroupDescriptions.Add(new PropertyGroupDescription("NumberOfOrder"));

    DataContext = collectionViewSource;
}

【问题讨论】:

  • .. ..有人吗? :(
  • 啊,现在我明白了 ;-) 你可以做的更简单:collectionViewSource.Source =ordersList;或者,如果您想使用 OrdersLocal 类,您可以使用 LINQ 查询:collectionViewSource.Source= ordersList.Select(x => new OrdersLocal() {Title = x.Title });
  • 谢谢兄弟,太棒了,顺便说一句,当我折叠订单时,是否可以放置一些文本(如每个组的标题文本),以便使用应用程序的人可以看到它的内容,即使订单是崩溃了。例如,我单击折叠,但我想看到像这样的文本 Order : numberofOrder,所以我可以确定我折叠的顺序 :)
  • hmm :)) 你能帮我处理这个分组项目的标题文本吗?有什么建议吗?
  • 您必须修改 GroupItem 的 ControlTemplate。我建议你提出一个新问题,因为如果我们混淆了你的所有后续问题,这可能会让其他人感到困惑

标签: c# wpf colors datagrid rows


【解决方案1】:

使用MultiDataTrigger 根据 a) 订单号和 b) 最后一行订单更改背景。您可能希望在模型中添加一个属性,说明该行是否是该订单的最后一行。

试试这样的东西(未经测试):

<Style.Triggers>
    <MultiDataTrigger>
        <MultiDataTrigger.Conditions>
            <Condition Binding="{Binding NumberOfOrder}" Value="1" />
            <Condition Binding="{Binding IsLastRow}" Value="True" />
        </MultiDataTrigger.Conditions>
        <Setter Property="Background" Value="Red" />
    </MultiDataTrigger>
    ...
</Style.Triggers>                   

【讨论】:

  • 不,它不能这样工作:/,当我同时加载 5 个订单时会发生什么? IsLastRow 是否应该识别每个订单的最后一行?然后画出来?
  • 我认为这就是您想要的,每个订单的最后一行都不同。你想要什么?空白行?
  • 我问你,即使所有订单在同一时间(例如五个订单),它是否应该识别每个订单的最后一行,该方法仍然会识别哪一行是最后一行互相画吗?
  • Here on another post OP 想要一种按订单号对行进行分组然后在分隔符中设置样式的方法。类似的东西?
  • 我会选择@Mat 的回答,他有一个很好的例子来说明如何使用分组。
【解决方案2】:

您可以尝试将绑定与值转换器一起使用。

我是这样处理单元格样式的:

<Style TargetType="DataGridCell">
    <Setter Property="Background"
            Value="{Binding State, Converter={x:Static l:Converters.CoupleStateConverter}}" />
                    </Style>

因此转换器根据状态返回背景颜色(在我的示例中为 int)。这与您的需求相似。

如您所见,单元格的数据上下文是行的值,因此我可以在示例中绑定到 Property State。我假设这对行有效,因此数据上下文将是要在该行中显示的项目。

【讨论】:

    【解决方案3】:

    您可以使用 CollectionViewSource 并按 NumberOfOrder 分组: XAML:

            <DataGrid ItemsSource="{Binding}" >
            <DataGrid.GroupStyle>
                <!-- Style for groups at top level. -->
                <GroupStyle>
                    <GroupStyle.ContainerStyle>
                        <Style TargetType="{x:Type GroupItem}">
                            <Setter Property="Template">
                                <Setter.Value>
                                    <ControlTemplate TargetType="{x:Type GroupItem}">
                                        <Expander IsExpanded="True">
                                            <Expander.Header>
                                                <DockPanel>
                                                    <TextBlock FontWeight="Bold"
                                                               Text="{Binding Path=Name}" />
                                                </DockPanel>
                                            </Expander.Header>
                                            <Expander.Content>
                                                <ItemsPresenter />
                                            </Expander.Content>
                                        </Expander>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </GroupStyle.ContainerStyle>
                </GroupStyle>
            </DataGrid.GroupStyle>
        </DataGrid>
    

    代码隐藏:

     CollectionViewSource collectionViewSource = new CollectionViewSource();
            collectionViewSource.Source = new List<RowItem>()
                {
                  new RowItem() {NumberOfOrder =1, Name ="kong foo" },
                  new RowItem() {NumberOfOrder =1,Name ="asdf" },
                  new RowItem() {NumberOfOrder =2,Name ="asdf" },
                  new RowItem() {NumberOfOrder =3,Name ="foo"}
                };
    
    
            collectionViewSource.GroupDescriptions.Add(new PropertyGroupDescription("NumberOfOrder"));
    
            DataContext = collectionViewSource;
    

    【讨论】:

    • 垫子,你的评论太有用了!很快我将发布我的代码,我仍然遇到问题,但我会尝试解决这个问题!
    • 垫子,我怎么能在这里应用 foreach 循环,在你的例子中,你向我展示了如何用 4 个对象解决这个问题,但想象一下我在数据库中有很多对象,我怎么能在这里循环对象并将其添加为新的 RowItem,我已经尝试过了,但我遇到错误:“INVALID INITIALIZER ...”
    • RowItem 只是一个示例类,您可以将其替换为例如MyDataBaseRowItem。这是如何从数据库中获取数据的?你使用任何 ORM(实体框架或类似的)吗?那么你已经有了一个可以使用的对象列表...
    • 是的,我明白了,这就是我所做的,让我发布代码,我现在将编辑我的问题,以便您检查我在说什么:)
    猜你喜欢
    • 2011-07-13
    • 1970-01-01
    • 2013-05-14
    • 1970-01-01
    • 2013-11-23
    • 1970-01-01
    • 2019-11-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多