自定义“伪GridView”---菜鸟三无残品系列
做.NET整整一年半了,天天混日子,技术也不行,浑浑噩噩的,过的平淡啊,偶尔出去自助游,总寻思着是不是要干点什么,原因无他,以前的日子太单调,想换个口味。
这不最近做了一个WPF项目,项目做完了,闲下来了,就不知道做什么了,上班吗,总得为自己找点事做,天天上网,浏览网页,聊天(把妹除外),听音乐,
天天反反复复的搞这些个有的没的事,说真的,没劲,还不如搞一些有实际的事,这样的事搞多了,你想要的东西或许会来的哦。
我一直认为我写这个总结是迫于无赖啊,却又不得不写,Why? 因为没有多余的钱出去旅游,太多我想去的地方不能去,想待的地方不能待,记得上次自己一个人
跑到杭州西湖那边去,什么都没有就一个包包,看着别人手里拿着各种设备,彻底的疼了,回来一想还是安心的待在苏州吧,安心工作,提升自己的实力吧。
但是怎么样提升自己的实力了,我ASP.NET不懂,WCF也不会,WPF连门也没有入,一句话什么都不懂,唯一会那么一丁点的就是总结。
前天因为要改点东西,打开了我最近做的一个WPF项目,说实话,我下面要写的东西没有一点技术含量,没有任何亮点,没有任何美感。
下面我们来说说需求吧:
我这个项目属于工厂监控的项目,例如客户那边有一条生产线,有10台机器,#1,#2.....#10,代表10台机器的编号,这10台机器类型相同,所产生的数据
类型是一致的,数据显示以网格形式显示。
如下图:
其实实际的需求比上面要求多一点,要求数据是实时更新,并且特定的数据显示特定的颜色,值类型的数据显示的背景色会根据定义的
颜色取值范围而 显示颜色。
下面是我依据项目敲的一个范例:
第一步 先看一下这个列子的项目截图:
第二步 思路介绍
实现的思路:在主界面先制定好整个GridView的排列形式,然后通过后台添加控件的方式来逐一添加数据(10台机械所产生的参数类型一致)。
主界面设计如下图:
接下来就是WPF前台代码的布局了...
代码如下:
<Window x:Class="WPFDemoOne.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Width="1048" Height="576"> <Border Background="#B3B3B3"> <Grid Grid.Column="0" Background="#50585D" TextBlock.Foreground="#FFFFFF" x:Name="XXOOGrid" TextBlock.FontSize="18" > <Grid.ColumnDefinitions> <ColumnDefinition Width="70"/> <ColumnDefinition Width="85"/> <ColumnDefinition Width="115"/> <ColumnDefinition/> <ColumnDefinition/> <ColumnDefinition/> <ColumnDefinition/> <ColumnDefinition/> <ColumnDefinition/> <ColumnDefinition/> <ColumnDefinition/> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> <RowDefinition /> <RowDefinition /> <RowDefinition /> <RowDefinition /> <RowDefinition /> <RowDefinition /> <RowDefinition /> <RowDefinition /> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions> <Border BorderBrush="#252525" BorderThickness="1 1 0 0" Grid.ColumnSpan="3"> <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="xxxxoooo"/> </Border> <Border BorderBrush="#252525" BorderThickness="1 1 0 0" Grid.ColumnSpan="3" Grid.Row="1" > <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="xxoo"/> </Border> <Border BorderBrush="#252525" BorderThickness="1 1 0 0" Grid.ColumnSpan="3" Grid.Row="2" > <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="xxoo"/> </Border> <Border BorderBrush="#252525" BorderThickness="1 1 0 0" Grid.ColumnSpan="3" Grid.Row="3" > <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="xxoo"/> </Border> <Border BorderBrush="#252525" BorderThickness="1 1 0 0" Grid.Row="4" Grid.ColumnSpan="3"> <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="xxoo"/> </Border> <Border BorderBrush="#252525" BorderThickness="1 1 0 1" Grid.Row="5" Grid.ColumnSpan="3"> <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="xxoo"/> </Border> <Border Grid.Column="0" Grid.RowSpan="6" BorderBrush="#252525" BorderThickness="1 1 0 0" Grid.Row="6"> <TextBlock Text="xxoo" Width="72" FontSize="12" TextAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" TextWrapping="Wrap"/> </Border> <Border BorderBrush="#252525" Grid.Column="1" Grid.Row="6" BorderThickness="1 1 0 0" Grid.RowSpan="2"> <TextBlock Text="xxoo" Width="60" FontSize="12" TextAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" TextWrapping="Wrap"/> </Border> <Border BorderBrush="#252525" Grid.Column="2" Grid.Row="6" BorderThickness="1 1 0 0"> <TextBlock Text="xxoo" HorizontalAlignment="Center" VerticalAlignment="Center"/> </Border> <Border BorderBrush="#252525" Grid.Column="2" Grid.Row="7" BorderThickness="1 1 0 0"> <TextBlock Text="xxoo" HorizontalAlignment="Center" VerticalAlignment="Center"/> </Border> <Border BorderBrush="#252525" Grid.Column="1" Grid.Row="8" BorderThickness="1 1 0 0" Grid.RowSpan="4"> <TextBlock Text="xxoo" Width="80" FontSize="12" TextAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" TextWrapping="Wrap"/> </Border> <Border BorderBrush="#252525" Grid.Column="2" Grid.Row="8" BorderThickness="1 1 0 0"> <TextBlock Text="xxoo" HorizontalAlignment="Center" VerticalAlignment="Center"/> </Border> <Border BorderBrush="#252525" Grid.Column="2" Grid.Row="9" BorderThickness="1 1 0 0"> <TextBlock Text="xxoo" HorizontalAlignment="Center" VerticalAlignment="Center"/> </Border> <Border BorderBrush="#252525" Grid.Column="2" Grid.Row="10" BorderThickness="1 1 0 0"> <TextBlock Text="xxoo" HorizontalAlignment="Center" VerticalAlignment="Center"/> </Border> <Border BorderBrush="#252525" Grid.Column="2" Grid.Row="11" BorderThickness="1 1 0 0"> <TextBlock Text="xxoo" HorizontalAlignment="Center" VerticalAlignment="Center"/> </Border> </Grid> </Border> </Window>
在让我们看看,Data.cs里面的代码吧。
在这个里面我定义了Name和value字段,value是显示在gridview里面的值。value值改变通知变更的有两个:value和Background。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Media; using System.ComponentModel; using WPFDemoOne; namespace WPFDemoOne { public class Demo:NotifyModel { public Demo() { } private string value; public string Value { get { return this.value; } set { this.value = value; NotifyPropertyChanged(()=>Value); NotifyPropertyChanged(()=>Background); } } private string name; public string Name { get { return name; } set { name = value; NotifyPropertyChanged(()=>Name); } } public SolidColorBrush Background { get { return GetColor(Value); } } SolidColorBrush titleBack = new SolidColorBrush() { Color = Color.FromArgb(0xFF, 0xB8, 0xCE, 0xDA) }; SolidColorBrush defaultBack = new SolidColorBrush() { Color = Color.FromArgb(0xFF, 0xE6, 0xE6, 0xE6) }; SolidColorBrush alarmBack = new SolidColorBrush() { Color = Color.FromArgb(0xFF, 0xFF, 0x00, 0x00) }; SolidColorBrush alarmYellow = new SolidColorBrush() { Color = Color.FromArgb(0xFF, 0xFF, 0xFF, 0x00) }; SolidColorBrush alarmGreen = new SolidColorBrush() { Color = Color.FromArgb(0xFF, 0x00, 0xFF, 0x03) }; SolidColorBrush alarmGrey = new SolidColorBrush() { Color = Color.FromArgb(0xFF, 0x80, 0x80, 0x80) }; private SolidColorBrush GetColor(string value) { if (!string.IsNullOrEmpty(value)) { if (Name == "9") { return alarmBack; } if (Name == "8") { return alarmYellow; } if (Name == "7") { return alarmGreen; } if (Name == "6") { return alarmGrey; } } return defaultBack; } } }
在来看一下NotifyModel.cs里面的代码吧。
其实这段代码是借鉴开源框架里面的东西,我注释的东西可能有问题,不怕误导的尽管看。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ComponentModel; using System.Linq.Expressions; namespace WPFDemoOne { public class NotifyModel:INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; public void NotifyPropertyChanged(string info) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(info)); } } public virtual void NotifyPropertyChanged<TProperty>(Expression<Func<TProperty>> property) { //创建一个lamdba的表达式,并获取其中的代码块 var lamdba=(LambdaExpression)property; MemberExpression meberExpression;//访问字段或者属性 //如果代码主题包含lamdba表达式 if (lamdba.Body is UnaryExpression) { //把主题转换成lamdba表达式 var unaryExpression = (UnaryExpression)lamdba.Body; //获取后面的字段名 meberExpression = (MemberExpression)unaryExpression.Operand; } else { //直接获取后面的字段名 meberExpression = (MemberExpression)lamdba.Body; } NotifyPropertyChanged(meberExpression.Member.Name); } } }
最后一个就是主界面的后台代码。
申明一点,其实项目中不是这样做的,建了一个gridHelper类,里面的数据也不是自己添加的,数据格式已经规定好了的,通过XML配置,来确定某一行的数据和取得数据的格式。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Threading; using System.Collections.ObjectModel; namespace WPFDemoOne { /// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); new Thread(new ThreadStart(Update)).Start(); CreateCol(); Loaded += new RoutedEventHandler(XXOOGrid_Load); Unloaded += new RoutedEventHandler(XXOOGrid_UnLoad); } ObservableCollection<ObservableCollection<Demo>> listKeys = new ObservableCollection<ObservableCollection<Demo>>(); private void Update() { while (true) { while (isUpdate) { //执行客户端UpdateData方法,刷新所有数据 App.Current.Dispatcher.Invoke(new Action(UpdateData)); Thread.Sleep(1000); } Thread.Sleep(5000);//刷新时间 if (!isUpdate) { break; } } } private void UpdateData() { //调用刷新数据的方法 RefreshDatas(); } private void CreateCol() { InitKeys(); //定义三种边框样式 var thick = new Thickness(1, 1, 0, 0); var thickcollast = new Thickness(1, 1, 1, 0); var thickrowlast = new Thickness(1, 1, 0, 1); var thickrowcollast = new Thickness(1, 1, 1, 1); //10代表有几列,为表头赋值 for (int i = 0; i < 10; i++) { //i+3是因为主界面左边有三列,如果是一列则改为i+1 BuildItem(new Demo() { Value = "#" + (i + 1) }, thick, "Value", 0, i + 3); } for (int i = 0; i < listKeys.Count; i++) { var row = listKeys[i]; for (int col = 0; col < row.Count; col++) { var key = row[col]; //如果不是最后一行和最后一列 if (col != row.Count - 1 && i != listKeys.Count - 1) { //i+1,因为表头已经赋值,故而是i+1,表头为#1,#2......#10 BuildItem(key, thickcollast, "Value", i + 1, 3 + col); } //不是第最后一行,但是最后一列 else if (col != row.Count - 1 && i == listKeys.Count - 1) { BuildItem(key, thickrowlast, "Value", i + 1, 3 + col); } else { BuildItem(key, thickrowcollast, "Value", i + 1, 3 + col); } } } } /// <summary> /// 创建textBlock并存放Value,border存放textBlock /// </summary> /// <param name="key">某一行一列对应的对象,例如第一行第一列的数据</param> /// <param name="thick">边框的样式</param> /// <param name="item">某一行一列对应的对象显示的字段</param> /// <param name="row">行是主界面的第几行</param> /// <param name="col">列是主界面的第几列</param> private void BuildItem(Demo key, Thickness thick, string item, int row, int col) { var text = new TextBlock(); text.VerticalAlignment = System.Windows.VerticalAlignment.Center; text.HorizontalAlignment = System.Windows.HorizontalAlignment.Center; text.SetBinding(TextBlock.TextProperty, item);//赋值 text.Foreground = new SolidColorBrush() { Color = Color.FromArgb(0xFF, 0x25, 0x25, 0x25) }; text.FontSize = 8; text.FontWeight = FontWeights.Bold; text.DataContext = key; var border = new Border(); border.BorderBrush = new SolidColorBrush() { Color = Color.FromArgb(0xFF, 0x25, 0x25, 0x25) }; border.BorderThickness = thick; border.Child = text; border.SetValue(Grid.RowProperty, row); border.SetValue(Grid.ColumnProperty, col); //设定第一行的颜色 if (row == 0) { border.Background = new SolidColorBrush() { Color = Color.FromArgb(0xFF, 0xB8, 0xCE, 0xDA) }; } //其他行的颜色 else { border.SetBinding(Border.BackgroundProperty, "Background"); border.DataContext = key; } XXOOGrid.Children.Add(border); } /// <summary> /// 循环遍历每一行并赋值 /// </summary> private void RefreshDatas() { foreach (var row in listKeys) { foreach (var m in row) { // var values = GetTagValue(m.Value); var value = m.Value; if (value == "NumberOne") { value = "1"; } if (m.Value != value) { m.Value = value; } } } } /// <summary> /// 备用方法, /// </summary> /// <param name="value"></param> /// <returns></returns> private string GetTagValue(string value) { //从这里获取数据的值,并替换成自己想要的值,例如value="NumberOne" return value; } void XXOOGrid_Load(object sender, RoutedEventArgs e) { isUpdate = true; } void XXOOGrid_UnLoad(object sender, RoutedEventArgs e) { isUpdate = false; } protected override void OnClosed(EventArgs e) { isUpdate = false; } private void InitKeys() { //从SQL或者XML中读取数据,这里是我自己手动给的数据 ObservableCollection<Demo> demoOne = new ObservableCollection<Demo>() { new Demo(){ Name="1",Value="NumberOne"}, new Demo(){ Name="2",Value="NumberTwo"}, new Demo(){ Name="3",Value="NumberThree"}, new Demo(){ Name="4",Value="NumberFour"}, new Demo(){ Name="5",Value="NumberFive"}, new Demo(){ Name="6",Value="NumberSix"}, new Demo(){ Name="7",Value="NumberSeven"}, new Demo(){ Name="8",Value="NumberEight"}, new Demo(){ Name="9",Value="NumberNine"}, new Demo(){ Name="10",Value="NumberTen"} }; listKeys.Add(demoOne); listKeys.Add(demoOne); listKeys.Add(demoOne); listKeys.Add(demoOne); listKeys.Add(demoOne); listKeys.Add(demoOne); listKeys.Add(demoOne); listKeys.Add(demoOne); listKeys.Add(demoOne); listKeys.Add(demoOne); listKeys.Add(demoOne); } public bool isUpdate { get; set; } } }
就这些了,哎,第一篇博客不容易,这是我头一次写这么长的东东,学不进去新的东西,只能巩固一下自己原有的知识,虽然东西有点简单,但是胜在是我第一次总结自己的项目。
有码有真相/Files/xuliangjie/GridView.rar