初步探讨WPF的ListView控件(涉及模板、查找子控件) - GavinJun
本文结合模板的应用初步介绍ListView的应用
一、Xaml中如何建立数据资源
大部分数据都会来自于后台代码,如何Xaml同样的建立数据源呢?比如建立一个学生List:
首先引入命名空间: xmlns:c="clr-namespace:System.Collections;assembly=mscorlib"
然后代码如下:
<c:ArrayList x:Key="stuList">
<local:Student Id="1" Name="小明" Grade="研一" Professional="计算机技术" HasJob="true"></local:Student>
<local:Student Id="2" Name="小李" Grade="大一" Professional="网络工程" HasJob="true"></local:Student>
<local:Student Id="3" Name="小张" Grade="研一" Professional="软件工程" HasJob="False"></local:Student>
<local:Student Id="4" Name="小王" Grade="研一" Professional="自动化控制" HasJob="true"></local:Student>
<local:Student Id="5" Name="大王" Grade="研一" Professional="软件设计" HasJob="False"></local:Student>
</c:ArrayList>
二、定义数据展示模板
展示数据使用的是ListView的View属性,MSDN解释:
Gets or sets an object that defines how the data is styled and organized in a ListView control. 说明是可以在里面放一些数据样式和一些控件模板的。其实这个Control暂时只能是GridView。每一个Student就是一列数据,我们要把学生显示到列上,所以就用到了GridView的GridViewColumn属性。关于GridView不在细说,请查阅MSDN。
ListView 控件样式和进行组织。 " data-guid="f64042b9-0226-2c38-1bd6-375526af84d1"> 最终数据是展示在GridViewColumn上面的,那么我们就开始设计我们GridViewColumn的数据模板,代码如下:
ListView 控件样式和进行组织。 " data-guid="f64042b9-0226-2c38-1bd6-375526af84d1">
<DataTemplate x:Key="NameDt">
<TextBox x:Name="textboxName" Text="{Binding Name}" GotFocus="textboxName_GotFocus"></TextBox>
</DataTemplate>
<DataTemplate x:Key="GradeDt">
<TextBox x:Name="textboxGrade" Text="{Binding Grade}"></TextBox>
</DataTemplate>
<DataTemplate x:Key="ProfessionalDt">
<TextBox x:Name="textboxProfessional" Text="{Binding Professional}"></TextBox>
</DataTemplate>
<DataTemplate x:Key="HasJobDt">
<CheckBox x:Name="CheckBocHasJob" IsChecked="{Binding HasJob}"></CheckBox>
</DataTemplate>
我们为每列数据定义了数据展示模板,当然你也可以自己定义别的,我仅仅是示例下! 三、使用ListView展示数据
有了以上的准备,下面就是通过ListView把数据和数据模板,通过绑定等联接起来了,需要注意的是,我们第二步定义的模板应用到的是CellTemplate上面,其实就是单元格的数据模板。
代码如下:
<ListView x:Name="ListViewStudent" ItemsSource="{StaticResource stuList}">
<ListView.View>
<GridView>
<GridViewColumn Header="ID" DisplayMemberBinding="{Binding Id}"></GridViewColumn>
<GridViewColumn Header="姓名" CellTemplate="{StaticResource NameDt}"></GridViewColumn>
<GridViewColumn Header="年级" CellTemplate="{StaticResource GradeDt}"></GridViewColumn>
<GridViewColumn Header="专业" CellTemplate="{StaticResource ProfessionalDt}"></GridViewColumn>
<GridViewColumn Header="已工作" CellTemplate="{StaticResource HasJobDt}"></GridViewColumn>
</GridView>
</ListView.View>
</ListView>
这样与运行程序,成功实现了绑定,并通过自己自定义的模板显示了数据,而且数据显示格式是自定义的,当然你可以不用模板,使用默认的模板,这样是不能改动数据的。默认的我就不介绍了。
四、ListView之数据操作
数据展示完了,那么数据操作呢?
比如我们有这么一个需求:当点击CheckBox时候,需要获取学生的信息,然后进行相关操作等。
我们在CheckBox的Checked事件下面写如下代码:
private void CheckBocHasJob_Checked(object sender, RoutedEventArgs e)
{ CheckBox tb = e.OriginalSource as CheckBox;
ContentPresenter cp = tb.TemplatedParent as ContentPresenter;
Student stu = cp.Content as Student;
MessageBox.Show(stu.Name + stu.Grade + stu.Professional); }
这段代码不难理解,首先通过 e.OriginalSource获取是那个控件触发的事件,通过控件的TemplatedParent属性,查找到上层的数据展示模板(其实是ListView视觉树里面的数据呈现模板)。这样通过Content属性即可获得Student的相关信息了。
五、Listview之控件查找
比如有这么一个需求:我想知道我点击选中checkbox的时候,这个CheckBox的控件名字是什么?
首先分析一下,CheckBox是模板里面的,不在逻辑树上,肯定要是用VaisualTreeHelper这个类,实现这个功能之前需要借助一个函数,此函数功能是获取控件逻辑树或视觉树上的指定类型控件。如下:
private ChildType FindVisualChild<ChildType>(DependencyObject obj) where ChildType : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(obj,i);
if (child!=null&& child is ChildType)
{
return child as ChildType;
}
else
{
ChildType childOfChildren = FindVisualChild<ChildType>(child);
if (childOfChildren!=null)
{
return childOfChildren;
}
}
}
return null; }
有了以上这个函数,功能就很好实现了,ListviewItem作为参数传入,查找CheckBox类型的控件即可:修改Checked事件代码如下:
private void CheckBocHasJob_Checked(object sender, RoutedEventArgs e)
{
//访问业务逻辑数据
CheckBox tb = e.OriginalSource as CheckBox;
ContentPresenter cp = tb.TemplatedParent as ContentPresenter;
Student stu = cp.Content as Student;
MessageBox.Show(stu.Name + stu.Grade + stu.Professional);
// this.ListViewStudent.SelectedItem = stu; //访问界面元素
ListViewItem lvi = this.ListViewStudent.ItemContainerGenerator.ContainerFromItem(stu) as ListViewItem;
CheckBox cb = FindVisualChild<CheckBox>(lvi);
MessageBox.Show(cb.Height + cb.Name + cb.Width); }
OK,这样你就可以成功获取到你想要的任何东西了~~~
全部代码:
Xaml:
<Window x:Class="ContentDataTemplate.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:c="clr-namespace:System.Collections;assembly=mscorlib"
xmlns:local="clr-namespace:ContentDataTemplate"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<c:ArrayList x:Key="stuList">
<local:Student Id="1" Name="小明" Grade="研一" Professional="计算机技术" HasJob="true"></local:Student>
<local:Student Id="2" Name="小李" Grade="大一" Professional="网络工程" HasJob="true"></local:Student>
<local:Student Id="3" Name="小张" Grade="研一" Professional="软件工程" HasJob="False"></local:Student>
<local:Student Id="4" Name="小王" Grade="研一" Professional="自动化控制" HasJob="true"></local:Student>
<local:Student Id="5" Name="大王" Grade="研一" Professional="软件设计" HasJob="False"></local:Student>
</c:ArrayList>
<DataTemplate x:Key="NameDt">
<TextBox x:Name="textboxName" Text="{Binding Name}" GotFocus="textboxName_GotFocus"></TextBox>
</DataTemplate>
<DataTemplate x:Key="GradeDt">
<TextBox x:Name="textboxGrade" Text="{Binding Grade}"></TextBox>
</DataTemplate>
<DataTemplate x:Key="ProfessionalDt">
<TextBox x:Name="textboxProfessional" Text="{Binding Professional}"></TextBox>
</DataTemplate>
<DataTemplate x:Key="HasJobDt">
<CheckBox x:Name="CheckBocHasJob" IsChecked="{Binding HasJob}" Checked="CheckBocHasJob_Checked"></CheckBox>
</DataTemplate>
</Window.Resources>
<Grid Margin="5">
<ListView x:Name="ListViewStudent" ItemsSource="{StaticResource stuList}">
<ListView.View>
<GridView>
<GridViewColumn Header="ID" DisplayMemberBinding="{Binding Id}"></GridViewColumn>
<GridViewColumn Header="姓名" CellTemplate="{StaticResource NameDt}"></GridViewColumn>
<GridViewColumn Header="年级" CellTemplate="{StaticResource GradeDt}"></GridViewColumn>
<GridViewColumn Header="专业" CellTemplate="{StaticResource ProfessionalDt}"></GridViewColumn>
<GridViewColumn Header="已工作" CellTemplate="{StaticResource HasJobDt}"></GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</Grid>
</Window>
C# CODE:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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; namespace ContentDataTemplate
{ class Student
{
public int Id { get; set; }
public string Name { get; set; }
public string Grade { get; set; }
public string Professional { get; set; }
public bool HasJob { get; set; }
}
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
} private void textboxName_GotFocus(object sender, RoutedEventArgs e)
{
//访问业务逻辑数据
TextBox tb = e.OriginalSource as TextBox;
ContentPresenter cp = tb.TemplatedParent as ContentPresenter;
Student stu = cp.Content as Student;
MessageBox.Show(stu.Name + stu.Grade + stu.Professional);
// this.ListViewStudent.SelectedItem = stu; //访问界面元素
ListViewItem lvi = this.ListViewStudent.ItemContainerGenerator.ContainerFromItem(stu) as ListViewItem;//获取ListViewItem
CheckBox cb = FindVisualChild<CheckBox>(lvi);
MessageBox.Show(cb.Name); }
/// <summary>
/// 寻找某个控件下的子控件
/// </summary>
/// <typeparam name="ChildType"></typeparam>
/// <param name="obj"></param>
/// <returns></returns>
private ChildType FindVisualChild<ChildType>(DependencyObject obj) where ChildType : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(obj,i);
if (child!=null&& child is ChildType)
{
return child as ChildType;
}
else
{
ChildType childOfChildren = FindVisualChild<ChildType>(child);
if (childOfChildren!=null)
{
return childOfChildren;
}
}
}
return null; } private void CheckBocHasJob_Checked(object sender, RoutedEventArgs e)
{
//访问业务逻辑数据
CheckBox tb = e.OriginalSource as CheckBox;
ContentPresenter cp = tb.TemplatedParent as ContentPresenter;
Student stu = cp.Content as Student;
MessageBox.Show(stu.Name + stu.Grade + stu.Professional);
// this.ListViewStudent.SelectedItem = stu; //访问界面元素
ListViewItem lvi = this.ListViewStudent.ItemContainerGenerator.ContainerFromItem(stu) as ListViewItem;
CheckBox cb = FindVisualChild<CheckBox>(lvi);
MessageBox.Show(cb.Height + cb.Name + cb.Width); }
}
}
后面我会继续深入介绍ListView的使用,包括样式、分组、排序等,敬请期待。
---------------------------------------------------------------------------------------------------------------------------------------------
作者:GavinDream(GavinJune主页 博客园) 出处: http://www.cnblogs.com/fuchongjundream/ 任何转载必须保留完整文章,在显要地方显示署名以及原文链接。如您有任何疑问或者授权方面的协商, 请发邮件给我 或者留言。
初步探讨WPF的ListView控件(涉及模板、查找子控件) - GavinJun的更多相关文章
- 初步探讨WPF的ListView控件(涉及模板、查找子控件)
本文结合模板的应用初步介绍ListView的应用 一.Xaml中如何建立数据资源 大部分数据都会来自于后台代码,如何Xaml同样的建立数据源呢?比如建立一个学生List: 首先引入命名空间: xmln ...
- 深入探讨WPF的ListView控件
接上一篇博客初步探讨WPF的ListView控件(涉及模板.查找子控件) 我们继续探讨ListView的用法 一.实现排序功能 需求是这样的:假如我们把学生的分数放入ListView,当我 ...
- WPF通过不透明蒙板切割显示子控件
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/Backspace110/article/ ...
- 【转】WPF查找子控件和父控件方法
一.查找某种类型的子控件,并返回一个List集合 public List<T> GetChildObjects<T>(DependencyObject obj, Type ty ...
- WPF查找子控件和父控件方法
一.查找某种类型的子控件,并返回一个List集合 public List<T> GetChildObjects<T>(DependencyObject obj, Type ty ...
- Repeater 模板中查找子控件
前言:对于Repeater控件,相信从事NETWeb开发的同仁们再熟悉不过了.因其呈现方式和Literal一样,并不在前端生成任何表单标签元素,所以属于比较轻量级的控件.不过青睐于Repeater的主 ...
- WPF中如何使用代码操作数据模板生成的控件
有一个Listbox,里面的Item是通过数据模板生成的,如下所示: <Border Margin="15" BorderBrush="Aqua" Bor ...
- C# WPF 父控件通过使用可视化树找到子控件
在我们使用WPF设计前台界面时,经常会重写数据模板,或者把控件放到数据模板里.但是一旦将控件放到数据模板中,在后台就没有办法通过控件的名字来获取它了,更没办法对它进行操作(例如,隐藏,改变控件的某个值 ...
- WPF布局控件与子控件的HorizontalAlignment/VerticalAlignment属性之间的关系
WPF布局控件与子控件的HorizontalAlignment/VerticalAlignment属性之间的关系: 1.Canvas/WrapPanel控件: 其子控件的HorizontalAlign ...
随机推荐
- Java 微信公众号开发--- 接入微信
开发微信公众号在没有正式的公众平台账号时,我们可以使用测试平台账号--- 测试平台申请地址:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandb ...
- Mysql多列索引实践
在网上看到: 定义:最左前缀原则指的的是在sql where 子句中一些条件或表达式中出现的列的顺序要保持和多索引的一致或以多列索引顺序出现,只要 出现非顺序出现.断层都无法利用到多列索引. 该博文有 ...
- 【webstrom】webstrom打开多个项目,webstrom常用快捷键
1.webstrom打开多个项目 默认情况下一次只能打开一个项目,如果需要打开多个就按照下面的方法 File -> settings -> Directories -> Add Co ...
- build android on macOS
http://blog.csdn.net/loften_93663469/article/details/51503293 @import url(http://i.cnblogs.com/Load. ...
- vue + django 的权限控制
用vue做前端页面, Django 提供api, 写了一个后台系统,结合方式是vue打包后的dist目录直接作为Django的静态目录, 这样的好处是不用配置Nginx具体的做法不在这里写了,记一下遇 ...
- Android之观察者/被观察者模式Observer/Observable
Android 本身也是有观察者模式的.虽然项目中很多需要通知数据改变的地方,用了EventBus,但是不得不说这个观察者模式还是很好用的.最近在开发新版本的时候引用了腾讯的IM,之前写直播的时候就用 ...
- js-数字渐增到指定的数字,在指定的时间内完成(有动画效果哦)插件jquery.animateNumber.js
本来在项目中我自己实现的效果是数字由0渐增到指定的数字就好. 但是,最终效果不理想! Why? 最终指定的数字太大了,TMMD,滚动好久就不到,那用户想看自己有多少钱了,那不是就一直等着!!!所以这个 ...
- android 什么时候call super.onDestory()等
Methods you override that are part of component creation (onCreate(), onStart(), onResume(), etc.), ...
- 1005 Spell It Right
1005 Spell It Right Given a non-negative integer N, your task is to compute the sum of all the dig ...
- golang实现dns域名解析(一)
本文将详细讲解如何用go语言一步一步实现dns域名解析的过程,并简单介绍点dns有关的知识,直接开始正题吧. 首先我们要了解dns解析的过程,没有了解的请看这里DNS入门(转)很详细.扫盲结束后,我们 ...