WPF中UserControl和DataTemplate
- 最新更新: http://denghejun.github.io
前言
前言总是留给我说一些无关主题的言论,WPF作为全新Microsoft桌面或web应用程序显示技术框架,
从08年开始,一直到现在,我也是在工作第一年后尝试去了解。且在网上也有很多对于该技术框架的
评论,有好也有坏的,有一部分同学说WPF只是在刚出来的时候才火,后边就落寞了,且现在国内外
通过WPF做出来的大型应用也没多少;另外一部分同学则认为,技术不论好坏,存在即合理,学习WPF
一定不会亏。不知道你们是怎么想的。我是觉得,本身对技术方面比较感兴趣,有时候会有自己的想法
来做一些东西,所以学习它会让我在想要做些东西的时候能有可用的技术,或是当别人谈及此事的时候,
至少我还知道。
UserControl
做过web开发或是winform的同学都知道,UserControl即是用户控件,是程序员根据需要自定义的一组
控件集合。WPF中当然也有,相比起来,更为简单,如下将会是一个简单的定义UserControl和使用的例子。
大概要实现的UI是这样子的,右边的是一组在ListBox内的CarItem集合,点击后在左边显示对应大图。
首先我们定义Car数据结构:
- // 简单起见,就一个Name属性
- public class MCar
- {
- public string Name { get; set; }
- }
接下来,设计右边的ItemTemplate,使用UserControl的方式,以下依次是UserControl的XAML和后台逻辑。
- <UserControl x:Class="WPFUserControl.CarsView.MainForm.CarItem"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- mc:Ignorable="d"
- d:DesignHeight="300" d:DesignWidth="300">
- <StackPanel>
- <Grid>
- <Grid.RowDefinitions>
- <RowDefinition ></RowDefinition>
- </Grid.RowDefinitions>
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="60"></ColumnDefinition>
- <ColumnDefinition Width="1*"></ColumnDefinition>
- </Grid.ColumnDefinitions>
- <Image Grid.Row="0" Grid.Column="0" x:Name="imgLogo" ></Image>
- <TextBlock Grid.Row="0" Grid.Column="1" x:Name="tbName"></TextBlock>
- </Grid>
- </StackPanel>
- </UserControl>
- /// <summary>
- /// CarItem.xaml 的交互逻辑
- /// </summary>
- public partial class CarItem : UserControl
- {
- private MCar car;
- public CarItem()
- {
- InitializeComponent();
- }
- public MCar Car
- {
- get { return this.car; }
- set
- {
- this.car = value;
- if (this.car == null)
- {
- return;
- }
- this.tbName.Text = this.car.Name;
- string uriStr = string.Format(@"/images/car/{0}.png", this.car.Name);
- this.imgLogo.Source = new BitmapImage(new Uri(uriStr, UriKind.Relative));
- }
- }
- }
然后是左边的详细模板,同样采用UserControl的方式:
- <UserControl x:Class="WPFUserControl.CarsView.MainForm.CarDetail"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- mc:Ignorable="d"
- d:DesignHeight="300" d:DesignWidth="300">
- <StackPanel>
- <Image x:Name="imgCarDetail"></Image>
- </StackPanel>
- </UserControl>
- /// <summary>
- /// CarDetail.xaml 的交互逻辑
- /// </summary>
- public partial class CarDetail : UserControl
- {
- private MCar car;
- public CarDetail()
- {
- InitializeComponent();
- }
- public MCar Car
- {
- get { return this.car; }
- set
- {
- this.car = value;
- if (this.car == null)
- {
- return;
- }
- string uriStr = string.Format(@"/images/car/{0}.png", this.car.Name);
- this.imgCarDetail.Source = new BitmapImage(new Uri(uriStr, UriKind.Relative));
- }
- }
- }
最后是主窗体的XAML布局代码:
- <Window x:Class="WPFUserControl.CarsView.MainForm.MainWindow"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:local="clr-namespace:WPFUserControl.CarsView.MainForm"
- Title="WPF_USECONTROL_MAINWINDOWS" Height="350" Width="525">
- <Grid>
- <Grid.RowDefinitions>
- <RowDefinition Height="*"></RowDefinition>
- </Grid.RowDefinitions>
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="3*"></ColumnDefinition>
- <ColumnDefinition Width="*"></ColumnDefinition>
- </Grid.ColumnDefinitions>
- <local:CarDetail x:Name="carDetail" Grid.Row="0" Grid.Column="0"></local:CarDetail>
- <ListBox x:Name="lbCarBox" Grid.Row="0" Grid.Column="1"></ListBox>
- </Grid>
- </Window>
让我们来看看后台的数据绑定是怎样实现的:
- /// <summary>
- /// MainWindow.xaml 的交互逻辑
- /// </summary>
- public partial class MainWindow : Window
- {
- public MainWindow()
- {
- InitializeComponent();
- this.InitializeCarView();
- }
- public void InitializeCarView()
- {
- BCarManagement carManager = new BCarManagement();
- List<MCar> carList = carManager.GetCarItemList();
- List<CarItem> carItemList = (from c in carList select new CarItem() { Car = c }).ToList();
- this.lbCarBox.ItemsSource = carItemList;
- this.lbCarBox.SelectionChanged += new SelectionChangedEventHandler((o, e) =>
- {
- CarItem item = e.AddedItems[] as CarItem;
- if (item == null)
- {
- return;
- }
- this.carDetail.Car = item.Car;
- });
- }
- }
初一看,和之前的webform或是winform中的用户控件相差无几,基本未用到WPF的一些特性,
所以WPF中较为重要的Template就是接下来所要提及的。
DataTemplate
Template实际上包括DataTemplate和ControlTemplate,ControlTemplate我们将会在下一章节详细介绍,
这里我们先用DataTemplate来改造之前的UserControl。将UserControl改造为DataTemplate十分简单,
只需要做部分调整即可,显示效果和前者是一模一样,但是,结构上较之前者来讲,清晰很多,这正是我们想要的。
我们将DataTemplate统一放到资源字典中,以便在不同的window中作为外部引用:
- <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:local="clr-namespace:WPFDataTemplate.CarsView.MainForm">
- <local:ImgUriConverter x:Key="imgConverter"></local:ImgUriConverter>
- <DataTemplate x:Key="carItemTemplate">
- <StackPanel>
- <Grid>
- <Grid.RowDefinitions>
- <RowDefinition ></RowDefinition>
- </Grid.RowDefinitions>
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="1*"></ColumnDefinition>
- <ColumnDefinition Width="1*"></ColumnDefinition>
- </Grid.ColumnDefinitions>
- <Image MaxWidth="100" Grid.Row="0" Grid.Column="0" Source="{Binding Name,Converter={StaticResource imgConverter}}" ></Image>
- <TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Name}"></TextBlock>
- </Grid>
- </StackPanel>
- </DataTemplate>
- <DataTemplate x:Key="carDetailTemplate">
- <StackPanel>
- <Image Source="{Binding Name,Converter={StaticResource imgConverter}}"></Image>
- </StackPanel>
- </DataTemplate>
- </ResourceDictionary>
以下是MainWindow的XAML代码:
- <Window x:Class="WPFDataTemplate.CarsView.MainForm.MainWindow"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- Title="WPF_DATATEMPLATE_MAINWINDOWS" Height="350" Icon="images/car/bc0.png" Width="525" WindowStyle="None" BorderThickness="0" >
- <Window.Resources>
- <ResourceDictionary Source="CarViewTemplate.xaml"></ResourceDictionary>
- </Window.Resources>
- <Grid>
- <Grid.RowDefinitions>
- <RowDefinition Height="9*"></RowDefinition>
- <RowDefinition></RowDefinition>
- </Grid.RowDefinitions>
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="3*"></ColumnDefinition>
- <ColumnDefinition Width="*"></ColumnDefinition>
- </Grid.ColumnDefinitions>
- <UserControl Grid.Column="0" Content="{Binding SelectedItem,ElementName=lbCarBox}" ContentTemplate="{StaticResource carDetailTemplate}"></UserControl>
- <ListBox x:Name="lbCarBox" Grid.Row="0" Grid.Column="1" ItemTemplate="{StaticResource carItemTemplate}"></ListBox>
- <Button x:Name="btnOpen" Width="125" Height="20" Grid.Row="1" Grid.Column="1"></Button>
- </Grid>
- </Window>
其中要注意的地方是,需要提前将外部资源引用进来。
接下来事ManWindow的分离代码(CodeBehind):
- /// <summary>
- /// MainWindow.xaml 的交互逻辑
- /// </summary>
- public partial class MainWindow : Window
- {
- public MainWindow()
- {
- InitializeComponent();
- this.lbCarBox.ItemsSource = new BCarManagement().GetCarItemList();
- this.KeyDown += new KeyEventHandler(MainWindow_KeyDown);
- this.MouseDown += new MouseButtonEventHandler(MainWindow_MouseDown);
- }
- void MainWindow_MouseDown(object sender, MouseButtonEventArgs e)
- {
- if (e.LeftButton == MouseButtonState.Pressed)
- {
- this.DragMove();
- }
- }
- void MainWindow_KeyDown(object sender, KeyEventArgs e)
- {
- if (e.Key == Key.Escape)
- {
- this.Close();
- }
- }
- }
你只需要关心窗体加载时的初始化函数即可。
至此,DataTemplate的改造结束。
小结
UserControl准确的讲是完全将view与data分离,分别对应在UserControl的XAML代码和CodeBehind代码,是一种显式
的将数据从UI中移植到后台,实际上他们最终会被编译成同一个类;
DataTemplate则是利用WPF的数据绑定特性,利用Bind将数据隐式的与XAML结合,是一种对数据如何展示的模板封装,
其便易性较好。
其实,UserControl与DataTemplate并无直接关系,UserControl直接体现在Control上,DataTemplate直接体现在
Template上。从上例中可看出我们将DataTemplate赋值给了UserControl的ContentTemplate属性。所以UserControl
是宏观上的控件,DataTemplate是对数据的模板化封装。
WPF中UserControl和DataTemplate的更多相关文章
- 通过WPF中UserControl内的按钮点击关闭父窗体
原文:通过WPF中UserControl内的按钮点击关闭父窗体 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/m0_37591671/article ...
- WPF中自定义的DataTemplate中的控件,在Window_Loaded事件中加载机制初探
原文:WPF中自定义的DataTemplate中的控件,在Window_Loaded事件中加载机制初探 最近因为项目需要,开始学习如何使用WPF开发桌面程序.使用WPF一段时间之后,感 ...
- 在WPF中UserControl
在这里我们将将打造一个UserControl(用户控件)来逐步讲解如何在WPF中自定义控件,并将WPF的一些新特性引入到自定义控件中来.我们制作了一个带语音报时功能的钟表控件, 效果如下: 在VS中右 ...
- WPF 中 UserControl作为另一个Process宿主到Window里, ErrorTemplate的默认红框没有出现
最近做WPF项目遇到一个问题, 我有2个process, 一个Process里只有Usercontrol, 另一个Process获取前一个Process中Usercontrol并host到当前的win ...
- wpf中UserControl的几种绑定方式
我们经常会抽取一些可重用的控件,某个属性是否需要重用,直接决定了这个属性的绑定方式. 1.完全不可重用的控件 有一些与业务强相关的控件,它们的属性完全来自ViewModel,越是相对复杂的控件,越容易 ...
- WPF中ControlTemplate和DataTemplate的区别
下面代码很好的解释了它们之间的区别: <Window x:Class="WPFTestMe.Window12" xmlns="http://schemas.micr ...
- wpf中在style的template寻找ControlTemplate和DataTemplate的控件
一.WPF中的两棵树 WPF中每个控件的Template都是由ControlTemplate构成,ControlTemplate包含了构成该控件的各种子控件,这些子控件就构成了VisualTree:而 ...
- WPF中的数据模板(DataTemplate)(转)
原文地址 http://www.cnblogs.com/zhouyinhui/archive/2007/03/30/694388.html WPF中的数据模板(DataTemplate) ...
- WPF中的数据模板(DataTemplate)
原文:WPF中的数据模板(DataTemplate) WPF中的数据模板(DataTemplate) ...
随机推荐
- Windows下图文详解PHP三种运行方式(php_mod、cgi、fastcgi)
PHP能不能成功的在Apache服务器上运行,就看我们如何去配置PHP的运行方式.PHP运行目前为止主要有三种方式: a.以模块加载的方式运行,初学者可能不容易理解,其实就是将PHP集成到Apache ...
- C++删除目录和复制目录函数
BOOL DeleteFolder(LPCTSTR lpszPath) { SHFILEOPSTRUCT FileOp; ZeroMemory((void*)&FileOp,sizeof(SH ...
- Android 如何在 ListView 中更新 ProgressBar 进度
=======================ListView原理============================== Android 的 ListView 的原理打个简单的比喻就是: 演员演 ...
- java学习第四天 类和变量
java也属于面向对象的编程 面向对象的三大特征: 封装 继承 多态 类 对象 对象:真实存在的唯一的事物 面向对象编程(oop)思想力图使对计算机语言中的事物的描述和自然界中的事物尽可能保持一致 ...
- java类读取properties文件
package com.bshinfo.el.userInfo.util; import java.io.BufferedReader;import java.io.File;import java. ...
- 配置https
引子: 最近在一篇文章中了解到EFF(电子前哨基金会)为了推广https协议,成立了一个let'sencrypt项目,可以发放免费的证书,此证书可以被大多数主流浏览器所信任,这个邪恶的念头一爆发,就让 ...
- SQL SERVER 中的提示
提示是指定的强制选项或策略,由 SQL Server 查询处理器针对 SELECT.INSERT.UPDATE 或 DELETE 语句执行. 提示将覆盖查询优化器可能为查询选择的任何执行计划. 注意: ...
- SourceTree安装教程和GitLab配置详解
一.安装Git 链接: http://pan.baidu.com/s/1mh7rICK 密码: 48dj 二.安装SourceTree 链接: http://pan.baidu.com/s/1skWk ...
- linq in not in
class A { public int B { get; set; } public string C { get; set; } } class Program { static void Mai ...
- 浅谈SQLiteOpenHelper之onUpgrade例子
当你看到这个博文,首先你要了解onCreate这个创建方法,再来继续下文!(可以参考我的上一个博文http://www.cnblogs.com/896240130Master/p/6119616.ht ...