原文:WPF之VirtualizingStackPanel.IsVirtualizing="False"

相信从winform转到wpf的人都遇到过这样的困惑,在处理DataGrid时,我想让某一单元格根据格式校验的不同情况显示不同的颜色,以便于用户区分。

于是你去查找各种资料,wpf下DataGrid如何改变某一单元格颜色,如果运气不好,可能搜索到的结果会令你失望,运气不错的话你会搜到类似如下代码:

  1. private void changeCell()
  2. {
  3. this.sj_DataGrid.Dispatcher.Invoke(
  4. new Action(
  5. delegate
  6. {
  7. foreach (LSErr l in lse)
  8. {
  9. for (int i = 0; i < this.sj_DataGrid.Items.Count; i++)
  10. {
  11. DataRowView drv = this.sj_DataGrid.Items[i] as DataRowView;
  12. DataGridRow row = (DataGridRow)this.sj_DataGrid.ItemContainerGenerator.ContainerFromIndex(i);
  13.  
  14. if (drv["StockCode"].ToString()==l.stCode)
  15. {
  16. System.Windows.Controls.Primitives.DataGridCellsPresenter presenter = GetVisualChild<System.Windows.Controls.Primitives.DataGridCellsPresenter>(row);
  17. if (presenter != null)
  18. {
  19. DataGridCell cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(l.ci);
  20. cell.Background = new SolidColorBrush(Colors.CadetBlue);
  21. }
  22. break;
  23. }
  24. }
  25. }
  26. }
  27. )
  28. );
  29. }
  30. //获取单元格
  31. public static T GetVisualChild<T>(Visual parent) where T : Visual
  32. {
  33.  
  34. T childContent = default(T);
  35. if (parent != null)
  36. {
  37. int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
  38. for (int i = 0; i < numVisuals; i++)
  39. {
  40. Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
  41. childContent = v as T;
  42. if (childContent == null)
  43. {
  44. childContent = GetVisualChild<T>(v);
  45. }
  46. if (childContent != null)
  47. {
  48. break;
  49. }
  50. }
  51. //Thread.Sleep(10);
  52. }
  53. return childContent;
  54. }

看起来很不错,而且运行也能成功。

不过很快你就会发现问题,那就是当你的窗口大小变化时,或者你拖动滚动条的时候奇葩的事情发生了,你选择变色的单元格变掉了,变色的可能是任何一个单元格,反正不是你想要的那一个。

于是你又再一次踏上了搜索之旅

终于让你找到了一个解决办法,就是我们标题中的VirtualizingStackPanel.IsVirtualizing="False",不错,效果很好,DataGrid应用这一属性之后我们可以准确的改变单元格颜色了。

但是,问题又来了...

当你的DataGrid加载的数据稍微多一些时,比如2000,3000,...10000...,再次运行你的程序你会发现主界面竟然卡住了好几秒,于是你设置断点查看,运行时间。你会发现由于ui虚拟化被禁用,数据加载的时间被无限拖长。用户界面卡顿,造成短时间内无响应,给用户死机的感受(PS:实际上此时程序正在玩儿命的绘制UI)

这种情况下,纵使你数据校验再好,数据校验整个过程中程序卡死的假象蒙蔽下,用户也会失去耐心,除非你的项目经理很强势,让用户耐心等待...

So,换一种实现策略吧

最终,还是暂时使用模板类中的触发器来实现吧,当不同的属性下生成不同的颜色

  1. <Window.Resources>
  2. <!--<c:ErrorConverter x:Key="ErrorConverter"/>-->
  3. <c:SheetArr x:Key="SheetCols"/>
  4. <Style TargetType="{x:Type Button}" x:Key="highlightStyle">
  5.  
  6. <Style.Triggers>
  7.  
  8. <Trigger Property="IsEnabled" Value="false">
  9.  
  10. <Setter Property="Background" Value="#EEEEEE" />
  11.  
  12. </Trigger>
  13.  
  14. <MultiTrigger>
  15.  
  16. <MultiTrigger.Conditions>
  17. <Condition Property="IsEnabled" Value="true" />
  18.  
  19. </MultiTrigger.Conditions>
  20.  
  21. <Setter Property="BorderBrush" Value="Red"/>
  22.  
  23. <Setter Property="FontSize" Value="14" />
  24.  
  25. <Setter Property="FontWeight" Value="Bold" />
  26.  
  27. <Setter Property="Foreground" Value="Red" />
  28.  
  29. </MultiTrigger>
  30.  
  31. </Style.Triggers>
  32.  
  33. </Style>
  34. <Style TargetType="{x:Type DataGridRow}">
  35. <Style.Triggers>
  36. <DataTrigger Binding="{Binding State}" Value="格式错误">
  37. <Setter Property="ToolTip">
  38. <Setter.Value>
  39. <ToolTip>
  40. <TextBlock Text="{Binding State,StringFormat='错误:{0}'}"/>
  41. </ToolTip>
  42. </Setter.Value>
  43. </Setter>
  44. <Setter Property="Foreground" Value="Red" />
  45. </DataTrigger>
  46. </Style.Triggers>
  47. </Style>
  48.  
  49. </Window.Resources>

这只是一种过度方案,当发现某单元格值达到某种条件时改变背景色,不够灵活,真正的解决这一问题还得研究wpf的ui visualization实现上下手

希望已经碰到这种问题的兄弟少走点儿弯路,或者如果有大神已经解决这种问题还请指教

WPF之VirtualizingStackPanel.IsVirtualizing="False"的更多相关文章

  1. WPF疑难杂症会诊

    原文:WPF疑难杂症会诊 为什么图片像素是模糊的? 容器边框设为非整数时,其内容中的像素图片会产生模糊,即使设置SnapsToDevicePixels="True"也无效. 以下是 ...

  2. 用WPF实现在ListView中的鼠标悬停Tooltip显示

    原文:用WPF实现在ListView中的鼠标悬停Tooltip显示 一.具体需求描述 在WPF下实现,当鼠标悬停在ListView中的某一元素的时候能弹出一个ToolTip以显示需要的信息. 二.代码 ...

  3. DataGrid当列宽超出当前宽度时,没有数据也恒有滚动条

    附件是DataGrid支持滚动条的文件. 具体使用如下: 1)DataGrid使用控件模板 <Setter Property="Template" Value="{ ...

  4. DataGrid 显示选中的item

    Datagrid或者listview 中想要把相应的项 滚动到当前可见的位置, 必须满足2个条件: 1) 必须去掉虚拟化      VirtualizingStackPanel.IsVirtualiz ...

  5. comobox在datagrid里,当滚动scrollbar时,会导致comobox选中项被重置的解决办法

    VirtualizingStackPanel.IsVirtualizing="False"

  6. WPF自定义控件与样式(6)-ScrollViewer与ListBox自定义样式

    一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: Scr ...

  7. WPF自定义控件与样式(7)-列表控件DataGrid与ListView自定义样式

    一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: Dat ...

  8. WPF自定义控件与样式(9)-树控件TreeView与菜单Menu-ContextMenu

    一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: 菜单M ...

  9. WPF自定义控件与样式(12)-缩略图ThumbnailImage /gif动画图/图片列表

    一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要针对WPF项目 ...

随机推荐

  1. jquery的mouseover和mouseout闪烁问题

    $(document).ready(function(){ $(".anli").hover( function(){ var $div = $(this); t = setInt ...

  2. Android自定义控件View(一)

    虽然Android API给我们提供了众多控件View来使用,但是鉴于Android的开发性,自然少不了根据需求自定义控件View了.比如说QQ头像是圆形的,但是纵观整个Android控件也找不到一个 ...

  3. .netcore consul实现服务注册与发现-集群完整版

    原文:.netcore consul实现服务注册与发现-集群完整版 一.Consul的集群介绍    Consul Agent有两种运行模式:Server和Client.这里的Server和Clien ...

  4. database software runInstaller无法看到全部的rac节点的处理方法

    近期遇到一个问题:rhel5.5下 安装11.2.0.4的rac.GI安装完了没问题. 可是 database software  runInstaller安装时,全部的节点在图形化界面中看不到. 搜 ...

  5. 利用for循环的嵌套输出图形--课后作业

    for (int i = 1; i <= 8; i++) { int a, b; for (a = 1; a < i; a++) Console.Write(" "); ...

  6. 写bug-free 的code

    一个算法题目 写的没有bug,是件不easy的事情 必需要考虑全面,事实上就是你算法过程中,每一个变量是否适用,你的算法是在什么样的前提以下展开的 这个和參数检查是另外一件事情.參数检查被说的好像是一 ...

  7. POJ 3714 Raid(平面近期点对)

    解题思路: 分治法求平面近期点对.点分成两部分,加个标记就好了. #include <iostream> #include <cstring> #include <cst ...

  8. 自动化部署脚本,给每一台主机装上JDK,且配好环境变量

    centos6.7 当我们有很多台主机,想在每台机器上都安装一样的某些软件,当然,一台机器一台机器安装也是可以的,但是如果有一键安装所有机器上的软件那是不是很激动人心呢! 首先我们需要制作一台服务器, ...

  9. fiddler AutoResponder(文件代理)

    测试网站https://www.meishij.net/ 目标:使用fiddler完成图片的替换 1.首先找到图片地址,然后在fiddler中查找对应图片 2.将对应的图片请求拖入到fiddler的A ...

  10. C 删除字符串1字符串2

    #include<stdio.h> #include<string.h> void main() { char s1[1000],s2[100],b[100]; int i,j ...