WPF之VirtualizingStackPanel.IsVirtualizing="False"

简介: 原文:WPF之VirtualizingStackPanel.IsVirtualizing="False" 相信从winform转到wpf的人都遇到过这样的困惑,在处理DataGrid时,我想让某一单元格根据格式校验的不同情况显示不同的颜色,以便于用户区分。
原文: WPF之VirtualizingStackPanel.IsVirtualizing="False"

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

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

private void changeCell() 
        {
            this.sj_DataGrid.Dispatcher.Invoke(
            new Action(
                delegate
                {
                    foreach (LSErr l in lse)
                    {
                        for (int i = 0; i < this.sj_DataGrid.Items.Count; i++)
                        {
                            DataRowView drv = this.sj_DataGrid.Items[i] as DataRowView;
                            DataGridRow row = (DataGridRow)this.sj_DataGrid.ItemContainerGenerator.ContainerFromIndex(i);


                            if (drv["StockCode"].ToString()==l.stCode)
                            {
                                System.Windows.Controls.Primitives.DataGridCellsPresenter presenter = GetVisualChild<System.Windows.Controls.Primitives.DataGridCellsPresenter>(row);
                                if (presenter != null)
                                {
                                    DataGridCell cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(l.ci);
                                    cell.Background = new SolidColorBrush(Colors.CadetBlue);
                                }
                                break;
                            }
                        }
                    }
                }
                )
                );
        }
//获取单元格
        public static T GetVisualChild<T>(Visual parent) where T : Visual
        {


            T childContent = default(T);
            if (parent != null)
            {
                int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
                for (int i = 0; i < numVisuals; i++)
                {
                    Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
                    childContent = v as T;
                    if (childContent == null)
                    {
                        childContent = GetVisualChild<T>(v);
                    }
                    if (childContent != null)
                    {
                        break;
                    }
                }
                //Thread.Sleep(10);
            }
            return childContent;
        }



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

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


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


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


但是,问题又来了...


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


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


So,换一种实现策略吧


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

<Window.Resources>
        <!--<c:ErrorConverter x:Key="ErrorConverter"/>-->
        <c:SheetArr x:Key="SheetCols"/>
        <Style TargetType="{x:Type Button}" x:Key="highlightStyle">


            <Style.Triggers>


                <Trigger Property="IsEnabled" Value="false">


                    <Setter Property="Background" Value="#EEEEEE" />


                </Trigger>

                <MultiTrigger>


                    <MultiTrigger.Conditions>
                        <Condition Property="IsEnabled" Value="true" />


                    </MultiTrigger.Conditions>


                    <Setter Property="BorderBrush" Value="Red"/>


                    <Setter Property="FontSize" Value="14" />


                    <Setter Property="FontWeight" Value="Bold" />


                    <Setter Property="Foreground" Value="Red" />


                </MultiTrigger>


            </Style.Triggers>


        </Style>
        <Style TargetType="{x:Type DataGridRow}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding State}" Value="格式错误">
                    <Setter Property="ToolTip">
                        <Setter.Value>
                            <ToolTip>
                                <TextBlock Text="{Binding State,StringFormat='错误:{0}'}"/>
                            </ToolTip>
                        </Setter.Value>
                    </Setter>
                    <Setter Property="Foreground" Value="Red" />
                </DataTrigger>
            </Style.Triggers>
        </Style>


    </Window.Resources>



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


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


目录
相关文章
|
C# 虚拟化 索引
【WPF】UI虚拟化之------自定义VirtualizingWrapPanel
原文:【WPF】UI虚拟化之------自定义VirtualizingWrapPanel 前言 前几天QA报了一个关于OOM的bug,在排查的过程中发现,ListBox控件中被塞入了过多的Item,而ListBox又定义了两种样式的ItemsPanelTemplate。
2268 0
|
7月前
|
开发框架 前端开发 JavaScript
在Winform界面使用自定义用户控件及TabelPanel和StackPanel布局控件
在Winform界面使用自定义用户控件及TabelPanel和StackPanel布局控件
|
C#
WPF技术之Separator控件
WPF Separator控件是一个用于在UI布局中创建水平或垂直分隔线的控件。该控件常用于分隔工具栏中的按钮或菜单中的选项。
870 0
WPF-Binding问题-模板样式使用Binding TemplatedParent与TemplateBinding区别
WPF-Binding问题-模板样式使用Binding TemplatedParent与TemplateBinding区别
298 0
|
C# 容器 数据可视化
WPF自定义TextBox及ScrollViewer
原文:WPF自定义TextBox及ScrollViewer   寒假过完,在家真心什么都做不了,可能年龄大了,再想以前那样能专心坐下来已经不行了。回来第一件事就是改了项目的一个bug,最近又新增了一个新的功能,为程序添加了一个消息栏。
1698 0
|
C# Windows
WPF实现炫酷Loading控件
原文:WPF实现炫酷Loading控件 Win8系统的Loading效果还是很不错的,网上也有人用CSS3等技术实现,研究了一下,并打算用WPF自定义一个Loading控件实现类似的效果,并可以让用户对Loading的颗粒(Particle)背景颜色进行自定义,话不多说,直接上代码: 1、用VS2...
1290 0
|
前端开发 C# 容器
WPF 蒙罩层 LoadingPage
原文:WPF 蒙罩层 LoadingPage WPF 蒙罩层 LoadingPage   前言   无论是在PC客户端,移动端,网站,在遇到长时间处理的时候都会需要用到蒙罩层,让用户有更好的体现。
1504 0
|
C#
WPF: FishEyePanel/FanPanel - 自定义Panel
原文:WPF: FishEyePanel/FanPanel - 自定义Panel 原文来自CodeProject,主要介绍如何创建自定义的Panel,如同Grid和StackPanel。
1304 0
|
C#
WPF Binding Mode,UpdateSourceTrigger
原文:WPF Binding Mode,UpdateSourceTrigger WPF 绑定模式(mode) 枚举值有5个1:OneWay(源变就更新目标属性)2:TwoWay(源变就更新目标并且目标变就更新源)3:OneTime(只根据源来设置目标,以后都不会变)4:OneWayToSource...
1585 0