博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
WPF中动态创建DataTemplate
阅读量:5138 次
发布时间:2019-06-13

本文共 5451 字,大约阅读时间需要 18 分钟。

众所周知,在WPF中,我们可以使用DataTemplate灵活地设计UI来呈现绑定的数据,对于不同数据,我们还可以使用DataTemplateSelector选择不同的DataTemplate。但是有时候,这还不能满足需求。这又要说到我正在开发的服装DRP,这并非打广告,而是我阐述的知识点都是在实际项目中碰到的,而且通过项目也好说明问题。

系统中有个报表叫下级订单分布,列出下级机构的订单量,如图:

其中订单量相关的单元格中的数字表示的含义:黑色数字表示剩余订单量,红色上标数字表示总订单量-已发货量。毫无疑问,这需要DataTemplate来实现。问题是下级机构的数量是不定的,即GridView绑定的数据列数是不一定的,几个到几百个都有可能(DataTemplateSelector就用不着考虑了),因此我们不能用实体类集合作为绑定数据源(动态增加属性,虽说C#4.0的动态特性大大增强了,但毕竟不是真正的动态语言,使用起来颇为不便,效率还挺低),而只能用DataTable/DataView,并且要动态地指定每个订单列的DataTemplate。假如使用实体类,那么订单列可以绑定到某个复杂属性(包含剩余订单量、总订单量、已发货量),这样DataTemplate只要在xaml中定义一次就可以了。但是既然使用的是DataTable,而DataTable假如从数据库获取的话,它的每一列的数据类型一般都是基本类型(复杂类型没试过,目测DataColumn只支持基础类型(错误,DataColumn支持复杂类型,且前端XAML绑定可写成“ColumnName.PropertyName”)),动态创建DataTemplate就必不可少了。

关于动态创建DataTemplate,我参考了的方法。代码如下: 

1 private void btnSearch_Click(object sender, RoutedEventArgs e) 2 { 3     while (gv.Columns.Count > 5) 4         gv.Columns.RemoveAt(5); 5     var data = _dataContext.GetSubordinateOrderDistribution(); 6     bool showAll = rbAllOrder.IsChecked.Value; 7     if (!showAll) 8         data.RemoveAll(o => o.QuaDelivered == o.Quantity); 9     DataTable table = new DataTable();10     table.Columns.Add(new DataColumn("ProductCode", typeof(string)));11     table.Columns.Add(new DataColumn("BrandCode", typeof(string)));12     table.Columns.Add(new DataColumn("StyleCode", typeof(string)));13     table.Columns.Add(new DataColumn("ColorCode", typeof(string)));14     table.Columns.Add(new DataColumn("SizeName", typeof(string)));15     var onames = data.Select(o => o.OrganizationName).Distinct().ToList();16     onames.Add("合计");17     foreach (var on in onames)18     {19         table.Columns.Add(new DataColumn(on, typeof(int)));20         table.Columns.Add(new DataColumn("delivered" + on, typeof(int)));21         table.Columns.Add(new DataColumn("all" + on, typeof(int)));22         //gv.Columns.Add(new GridViewDataColumn() { Header = on, Name = on, DataMemberBinding = new Binding(on) });23         var col = new GridViewDataColumn() { Header = on, Name = on, DataMemberBinding = new Binding(on) };24         //内存中动态生成一个XAML,描述了一个DataTemplate25         XNamespace ns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation";26         XElement xGrid = new XElement(ns + "Grid", new XElement(ns + "Grid.ColumnDefinitions", new XElement(ns + "ColumnDefinition", new XAttribute("Width", "Auto")), new XElement(ns + "ColumnDefinition", new XAttribute("Width", "Auto"))));27         xGrid.Add(new XElement(ns + "TextBlock", new XAttribute("Text", "{Binding Path=" + on + "}"), new XAttribute("Margin", "0 0 5 0")));28         if (showAll)29         {30             xGrid.Add(31                 new XElement(ns + "TextBlock", new XAttribute("Foreground", "Red"), new XAttribute("Text", "{Binding Path=" + "delivered" + on + "}"), new XAttribute("FontSize", "8"), new XAttribute("Grid.Column", "1")));32         }33         else34         {35             xGrid.Add(36                 new XElement(ns + "TextBlock", new XAttribute("Foreground", "Red"), new XAttribute("FontSize", "8"), new XAttribute("Grid.Column", "1"),37                 new XElement(ns + "TextBlock", new XAttribute("Text", "{Binding Path=" + "all" + on + "}")),38                 new XElement(ns + "TextBlock", new XAttribute("Text", "-")),39                 new XElement(ns + "TextBlock", new XAttribute("Text", "{Binding Path=" + "delivered" + on + "}"))));40         }41         XElement xDataTemplate = new XElement(ns + "DataTemplate", new XAttribute("xmlns", "http://schemas.microsoft.com/winfx/2006/xaml/presentation"));42         xDataTemplate.Add(xGrid);43         XmlReader xr = xDataTemplate.CreateReader();44         DataTemplate dataTemplate = XamlReader.Load(xr) as DataTemplate;45         col.CellTemplate = dataTemplate;46         gv.Columns.Add(col);47     }48     var ps = data.OrderBy(o => o.ProductCode).Select(o => o.ProductID).Distinct();49     foreach (var p in ps)50     {51         var d = data.First(o => o.ProductID == p);52         DataRow row = table.NewRow();53         table.Rows.Add(row);54         row["ProductCode"] = d.ProductCode;55         row["BrandCode"] = d.BrandCode;56         row["StyleCode"] = d.StyleCode;57         row["ColorCode"] = d.ColorCode;58         row["SizeName"] = d.SizeName;59         foreach (var on in onames)60         {61             if (on == "合计")62             {63                 var totalData = data.Where(o => o.ProductID == p);64                 var quantity = totalData.Sum(o => o.Quantity);65                 var quaDelivered = totalData.Sum(o => o.QuaDelivered);66                 row[on] = showAll ? quantity : (quantity - quaDelivered);67                 row["all" + on] = quantity;68                 row["delivered" + on] = quaDelivered;69                 continue;70             }71             d = data.Find(o => o.ProductID == p && o.OrganizationName == on);72             if (d != null)73             {74                 row[on] = showAll ? d.Quantity : (d.Quantity - d.QuaDelivered);75                 row["all" + on] = d.Quantity;76                 row["delivered" + on] = d.QuaDelivered;77             }78         }79     }80     gv.ItemsSource = table.DefaultView;81 }

 注意最后ItemsSource设置成DefaultView,如果直接用DataTable那么CellTemplate的Binding就有问题,无法绑定,不知何故。另外XElement xDataTemplate = new XElement(ns + "DataTemplate", new XAttribute("xmlns", )); ns和xmlns属性声明都不能忽略,否则会报错。

转载请注明本文出处:

转载于:https://www.cnblogs.com/newton/archive/2012/12/13/2816753.html

你可能感兴趣的文章
【概率】poj 2096:Collecting Bugs
查看>>
javascript 无限分类
查看>>
【自制插件】MMD4Maya
查看>>
解决linux服务器乱码
查看>>
mapbox.gl文字标注算法基本介绍
查看>>
【C++】异常简述(二):C++的异常处理机制
查看>>
web.config在哪里
查看>>
SQL Server 2000 版本支持的最大物理内存量
查看>>
spring IOC装配Bean(注解方式)
查看>>
[面试算法题]有序列表删除节点-leetcode学习之旅(4)
查看>>
SpringBoot系列五:SpringBoot错误处理(数据验证、处理错误页、全局异常)
查看>>
kubernetes_book
查看>>
Redis 常用数据结构命令
查看>>
软件工程课堂作业
查看>>
OpenFire 的安装和配置
查看>>
web.config详解
查看>>
ZJOI2018游记Round1
查看>>
侧边栏广告和回到顶部
查看>>
https://blog.csdn.net/u012106306/article/details/80760744
查看>>
【转】从头到尾彻底理解KMP
查看>>