【问题标题】:How to style a WPF DataGridCell dynamically如何动态设置 WPF DataGridCell 样式
【发布时间】:2011-02-01 15:58:16
【问题描述】:

我有一个 DataGrid,其 itemsSource 定义如下:

dg.ItemsSource = new ObservableCollection<myRow>

...

public class myRow : Collection<myDataGridCell> { ... }

...

public interface ImyDataGridCell
{
    Brush Background { get; set; }
    Brush Foreground { get; set; }
}

然后我为每种类型的列/单元格设置了类:

public class myTextBoxColumn : DataGridTextColumn {...}
public class myTextBoxCell : TextBox, ImyDataGridCell {...}

然后我像这样设置每一列的 CellStyle:

在每一列的构造函数中:

string source = String.Format(CultureInfo.InvariantCulture, "[{0}].", dataGrid.Columns.Count);
// I set the "source" string to the column's index in the dataGrid's Columns list between [] to get an index in my binding below.

CellStyle = new Style(typeof(DataGridCell));
CellStyle.Setters.Add(new Setter(DataGridCell.BackgroundProperty, new Binding(source + "Background")));

这使我可以将实际 DataGridCell 的 Background 属性绑定到我的单元格表示的 Background 属性,从而可以随时轻松地修改单元格的背景。

现在我的主要问题是这种做事方式会像地狱一样减慢 dataGrid... 我为每个单元格绑定了大约 15 个属性,当我显示 100 cols x 20 行时,显示 dataGrid 需要一秒钟多的时间,然后当我水平滚动时大约需要一秒钟来刷新它(我的屏幕只能允许 20 cols,并且我为 dataGrid 启用了虚拟化)。

如果我去掉样式,响应时间仍然超出我的预期,但我可以做到。

那么有没有更好的方法来做到这一点?

我也尝试在 Xaml 中使用这种样式,但它似乎不能很好地处理列的虚拟化,即:我将单元格的背景设置为绿色,然后向右滚动整个页面,并且单元格以相同的方式结束位置,因为我涂成绿色的单元格如果应该是红色,则会获得绿色事件:在我将当前行移动到包含该单元格的行之前,该值不会更新... 另外,它似乎根本没有提高性能...

感谢您的分享,如果您对此事有任何虽然/提示/以前的经验,我愿意尝试一切可以使这个该死的 dataGrid 加载更快...

编辑:我想要达到的一般效果:

  • 具有动态列的 dataGrid(列的数量和类型仅在运行时知道
  • 在任何时候,我都可以更改单个单元格的任何样式属性:字体(如果应用了系列、大小、样式、粗细、装饰)、前景、背景、textAlignment(如果有)等...

这正是我必须实现的。 知道我发现启用列虚拟化后,您无法操作 REAL dataGridCells,因为它们可能尚未显示(虚拟化),然后您失去了属性值的更改。所以我选择了这个“hack”:我将实际 dataGridCell 样式中的每个属性都绑定到“逻辑”属性,然后修改逻辑属性。但这太慢了。

希望我能更好地解释自己。

【问题讨论】:

    标签: wpf datagrid binding styling datagridcell


    【解决方案1】:

    有机会看到你的慢 Xaml 吗?我原以为使用数据触发器执行此操作不会太糟糕(而且您使用的数据网格版本是 .net 4.0 和 WPF Toolkit 版本不同)

    我已经完成了这样的事情来为选定的项目重新着色,它似乎并没有太慢(这不是正确的解决方案,但在我说更多之前,我想了解更多细节):

            <Style TargetType="DataGrid">
            <Setter Property="CellStyle">
                <Setter.Value>
                    <Style TargetType="DataGridCell">
                        <Style.Triggers>
                            <Trigger Property="IsSelected" Value="True">
                                <Setter Property="Background" Value="{StaticResource SelectedBackgroundBrush}" />
                                <Setter Property="BorderBrush" Value="{x:Null}" />
                                <Setter Property="Foreground" Value="White" />
                            </Trigger>
                        </Style.Triggers>
                    </Style>
                </Setter.Value>
            </Setter>
        </Style>
    

    【讨论】:

    • 其实我想我想问的是你想要的最终效果是什么?如果您为 15 个属性执行此操作,那么性能不会很好。数据模板和触发器可能会更好。
    • @Peterl:感谢您的反馈,我编辑了我的问题并提供了更多详细信息,希望这可以帮助您解决我的问题。就我而言,使用触发器毫无意义,因为视觉属性与任何东西都没有关联。我只需要随时可以说:“嘿,这个单元格看起来是灰色的,让我们给它一个粉红色的背景!”。所以我只需要能够改变背景颜色...
    • 我想我可以看到你在做什么(我希望你不是)。你可以拥有一套“风格”而不是单独的颜色吗?认为我需要在这里放置一个样本来玩,感觉就像我们需要 a) 有一组样式(“快乐”、“悲伤”、“愤怒”等),然后应用于每个单元格(你能摆脱这个?)b)用SetValue调用做一些有趣的事情或c)找到一些方法来使属性绑定动态化。嗯需要构建一个小测试应用程序。 (在评论框忘记了大约 5 分钟)
    • @Peterl:您仍然可以删除第一条评论(鼠标悬停时在右侧交叉)。另外,忘记样式集,这当然太容易了;)...我需要能够在任何时候应用任何样式,而无需事先知道它们,而且更糟糕的是,每个属性独立于另一个(即:有时只是改变背景,有时只是前景,有时两者兼而有之,这有 15 种属性组合)......因此我把头发拉下来......
    猜你喜欢
    • 2014-06-13
    • 1970-01-01
    • 1970-01-01
    • 2011-02-19
    • 1970-01-01
    • 2013-11-26
    • 2014-11-11
    • 1970-01-01
    相关资源
    最近更新 更多