最新更新: 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的更多相关文章

  1. 通过WPF中UserControl内的按钮点击关闭父窗体

    原文:通过WPF中UserControl内的按钮点击关闭父窗体 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/m0_37591671/article ...

  2. WPF中自定义的DataTemplate中的控件,在Window_Loaded事件中加载机制初探

    原文:WPF中自定义的DataTemplate中的控件,在Window_Loaded事件中加载机制初探         最近因为项目需要,开始学习如何使用WPF开发桌面程序.使用WPF一段时间之后,感 ...

  3. 在WPF中UserControl

    在这里我们将将打造一个UserControl(用户控件)来逐步讲解如何在WPF中自定义控件,并将WPF的一些新特性引入到自定义控件中来.我们制作了一个带语音报时功能的钟表控件, 效果如下: 在VS中右 ...

  4. WPF 中 UserControl作为另一个Process宿主到Window里, ErrorTemplate的默认红框没有出现

    最近做WPF项目遇到一个问题, 我有2个process, 一个Process里只有Usercontrol, 另一个Process获取前一个Process中Usercontrol并host到当前的win ...

  5. wpf中UserControl的几种绑定方式

    我们经常会抽取一些可重用的控件,某个属性是否需要重用,直接决定了这个属性的绑定方式. 1.完全不可重用的控件 有一些与业务强相关的控件,它们的属性完全来自ViewModel,越是相对复杂的控件,越容易 ...

  6. WPF中ControlTemplate和DataTemplate的区别

    下面代码很好的解释了它们之间的区别: <Window x:Class="WPFTestMe.Window12" xmlns="http://schemas.micr ...

  7. wpf中在style的template寻找ControlTemplate和DataTemplate的控件

    一.WPF中的两棵树 WPF中每个控件的Template都是由ControlTemplate构成,ControlTemplate包含了构成该控件的各种子控件,这些子控件就构成了VisualTree:而 ...

  8. WPF中的数据模板(DataTemplate)(转)

    原文地址 http://www.cnblogs.com/zhouyinhui/archive/2007/03/30/694388.html WPF中的数据模板(DataTemplate)        ...

  9. WPF中的数据模板(DataTemplate)

    原文:WPF中的数据模板(DataTemplate) WPF中的数据模板(DataTemplate)                                                   ...

随机推荐

  1. 提高MYSQL百万条数据的查询速度

    提高MYSQL百万条数据的查询速度 1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 nul ...

  2. C和指针 第十章 结构和联合 (二)

    结构体传值: 结构体也是标量,像字符和整数一样,可以传递给一个函数,但是传入整个结构体效率很低,可以传入指向结构体的指针来提高效率.如果不希望程序对结构体变量改变可以加入const关键词. typed ...

  3. ubuntu15.10安装搜狗拼音输入法

    sudo vim /etc/apt/sources.list.d/ubuntukylin.list(我的默认显示没有这个文件将自动创建) 添加源deb http://archive.ubuntukyl ...

  4. espcms内容页上下篇按后台手动排序号

    模板文件: {%get name=plist class="did":$read.did,pid:$read.pid%} <li class="fl"&g ...

  5. Spark集群部署

    Spark是通用的基于内存计算的大数据框架,可以和hadoop生态系统很好的兼容,以下来部署Spark集群 集群环境:3节点 Master:bigdata1 Slaves:bigdata2,bigda ...

  6. Xcode 中的相对路径与绝对路径的相关设置

    近日闲来无事,与博客园中闲荡,忽至一烟霞照耀祥瑞蒸熏松竹翠秀奇花遍开的神奇之地.如此美景,令人心生向往,故而徜徉于其中不可自拔,独乐乐不如众乐乐: iOS开发之 相对路径与绝对路径 https://d ...

  7. PHP字符串处理

    /*1 字符串格式化 */ $str = ' php '; //清理两边的空格trim();,左边ltrim(); 边rtrin() echo trim($str); //nl2br();将换行符\n ...

  8. MVC学习笔记----缓存

    http://www.cnblogs.com/darrenji/p/3683306.html   视图缓存 http://www.cnblogs.com/darrenji/p/3649994.html ...

  9. XD, XR, DR 股票

    股权登记日与除权除息日 所以,如果投资者想得到一家上市公司的分红.配股权,就必须弄清这家公司的股权登记日在哪一天,否则就会失去分红.配股的机会. 股权登记日后的第一天就是除权日或除息日,这一天或以后购 ...

  10. 如何在插件中添加Actor类

    只要按照BlueprintFunctionLibrary的那个模板做就好了,把用编辑器生成的代码复制到插件对应的目录 之后需要注意做以下修改 1.H文件中的 GENERATED_UCLASS_BODY ...