控件(Control)是数据内容表现形式和算法内容表现形式的双重载体。
控件的“算法内容”:控件能展示哪些数据,具有哪些方法,能响应哪些操作,能激发什么事件,简而言之就是控件的功能,是一组相关的算法逻辑;
控件的“数据内容”:控件所展示的具体内容是什么。
在WPF中,通过引入模板(Template)将数据和算法的“内容”和“形式”解耦。WPF中的Template分为两大类:
(1)、ControlTemplate:算法内容的表现形式。一个控件怎样组织其内部结构才能让它更符合业务逻辑、让用户操作起来更舒服就由它来控制;
(2)、DataTemplate:数据内容的表现形式。决定一条数据显示成什么样子,是简单地文本还是直观的图形动画。
Template就是“外衣”:ControlTemplate是空间的外衣,DataTemplate是数据的外衣。
WPF中的控件不再具有固定的形象,仅仅是算法内容或数据内容的载体。
一样的内容可以用不同的形式来展现,软件设计称之为“数据--视图”(Data_View)模式。
DataTemplate常用的地方有3处:
(1)、ContentControl的ContentTemplate属性;
(2)、ItemsControl的ItemTemplate属性;
(3)、GridViewColumn的CellTemplate属性。
一下两个示例比较:
(1)、没有使用DataTemplate
public class Car
{
public string Automaker { get; set; }
public string Name { get; set; }
public string Year { get; set; }
public string TopSpeed { get; set; }
}
---------------------------------------------------------------------------------------------------------
<UserControl x:Class="MyTestWpfApplication.CarListItemView"
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="100" d:DesignWidth="100">
<Grid Margin="2">
<StackPanel Orientation="Horizontal">
<Image x:Name="imageLogo" Width="64" Height="64"/>
<StackPanel Margin="5, 10">
<TextBlock x:Name="textBlockName" FontSize="16" FontWeight="Bold"/>
<TextBlock x:Name="textBlockYear" FontSize="14"/>
</StackPanel>
</StackPanel>
</Grid>
</UserControl>
public partial class CarListItemView : UserControl
{
private Car car;
public Car Car
{
get { return car; }
set
{
car = value;
this.textBlockName.Text = car.Name;
this.textBlockYear.Text = car.Year;
string strUri = string.Format(@"/Resources/Logos/{0}.png", car.Automaker);
this.imageLogo.Source = new BitmapImage(new Uri(strUri, UriKind.Relative));
}
}
public CarListItemView()
{
InitializeComponent();
}
}
--------------------------------------------------------------------------------------------------------------------
<UserControl x:Class="MyTestWpfApplication.CarDetailView"
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" >
<Border BorderBrush="Black" BorderThickness="1" CornerRadius="6">
<StackPanel Margin="5">
<Image x:Name="imagePhoto" Width="400" Height="250"/>
<StackPanel Orientation="Horizontal" Margin="5, 0">
<TextBlock Text="Name:" FontWeight="Bold" FontSize="20"/>
<TextBlock x:Name="textBlockName" FontSize="20" Margin="5, 0"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="5, 0">
<TextBlock Text="Automaker:" FontWeight="Bold"/>
<TextBlock x:Name="textBlockAutomaker" Margin="5, 0"/>
<TextBlock Text="Year:" FontWeight="Bold"/>
<TextBlock x:Name="textBlockYear" Margin="5, 0"/>
<TextBlock Text="Top Speed:" FontWeight="Bold"/>
<TextBlock x:Name="textBlockTopSpeed" Margin="5, 0"/>
</StackPanel>
</StackPanel>
</Border>
</UserControl>
public partial class CarDetailView : UserControl
{
private Car car;
public Car Car
{
get { return car; }
set
{
car = value;
this.textBlockName.Text = car.Name;
this.textBlockYear.Text = car.Year;
this.textBlockTopSpeed.Text = car.TopSpeed;
this.textBlockAutomaker.Text = car.Automaker;
string strUri = string.Format(@"/Resources/Images/{0}.jpg", car.Name);
this.imagePhoto.Source = new BitmapImage(new Uri(strUri, UriKind.Relative));
}
}
public CarDetailView()
{
InitializeComponent();
}
}
----------------------------------------------------------------------------------------------------------------------------------
<Window x:Class="MyTestWpfApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyTestWpfApplication"
Title="MainWindow" Height="350" Width="623">
<StackPanel Orientation="Horizontal" Margin="5">
<local:CarDetailView x:Name="detailView"/>
<ListBox x:Name="listBoxCars" Width="180" Margin="5, 0" SelectionChanged="listBoxCars_SelectionChanged"/>
</StackPanel>
</Window>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
InitializeCarList();
}
private void InitializeCarList()
{
List<Car> carList = new List<Car>
{
new Car{Automaker = "Lamborghini", Name = "Diablo", Year = "1990", TopSpeed = "340"},
new Car{Automaker = "Lamborghini", Name = "Murcielago", Year = "2001", TopSpeed = "353"},
new Car{Automaker = "Lamborghini", Name = "Gallardo", Year = "2003", TopSpeed = "325"},
new Car{Automaker = "Lamborghini", Name = "Reventon", Year = "2008", TopSpeed = "356"}
};
foreach (Car car in carList)
{
CarListItemView view = new CarListItemView();
view.Car = car;
this.listBoxCars.Items.Add(view);
}
}
private void listBoxCars_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
CarListItemView view = e.AddedItems[0] as CarListItemView;
if (null != view)
this.detailView.Car = view.Car;
}
}
===============================================================================
(2)、使用DataTemplate:
public class Car
{
public string Automaker { get; set; }
public string Name { get; set; }
public string Year { get; set; }
public string TopSpeed { get; set; }
}
------------------------------------------------------------------------
public class AutomakerToLogoPathConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string strUri = string.Format(@"/Resources/Logos/{0}.png", (string)value);
return new BitmapImage(new Uri(strUri, UriKind.Relative));
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
public class NameToPhotoPathConverter :IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string strUri = string.Format(@"/Resources/Images/{0}.jpg", (string)value);
return new BitmapImage(new Uri(strUri, UriKind.Relative));
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
----------------------------------------------------------------------------------------------------------------
<Window x:Class="MyTestWpfApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyTestWpfApplication"
Title="MainWindow" Height="350" Width="623">
<Window.Resources>
<!--Converter-->
<local:AutomakerToLogoPathConverter x:Key="a2l"/>
<local:NameToPhotoPathConverter x:Key="n2p"/>
<!--DataTemplate for Detail View-->
<DataTemplate x:Key="carDetailViewTemplate">
<Border BorderBrush="Black" BorderThickness="1" CornerRadius="6">
<StackPanel Margin="5">
<Image Width="400" Height="250" Source="{Binding Name, Converter={StaticResource ResourceKey=n2p}}"/>
<StackPanel Orientation="Horizontal" Margin="5, 0">
<TextBlock Text="Name:" FontWeight="Bold" FontSize="20"/>
<TextBlock Text="{Binding Name}" FontSize="20" Margin="5, 0"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="5, 0">
<TextBlock Text="Automaker:" FontWeight="Bold"/>
<TextBlock Text="{Binding Automaker}" Margin="5, 0"/>
<TextBlock Text="Year:" FontWeight="Bold"/>
<TextBlock Text="{Binding Year}" Margin="5, 0"/>
<TextBlock Text="Top Speed:" FontWeight="Bold"/>
<TextBlock Text="{Binding TopSpeed}" Margin="5, 0"/>
</StackPanel>
</StackPanel>
</Border>
</DataTemplate>
<!--DataTemplate For Item View-->
<DataTemplate x:Key="carListItemViewTemplate">
<Grid Margin="2">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Automaker, Converter={StaticResource ResourceKey=a2l}}" Grid.RowSpan="3" Width="64" Height="64"/>
<StackPanel Margin="5, 10">
<TextBlock Text="{Binding Name}" FontSize="16" FontWeight="Bold"/>
<TextBlock Text="{Binding Year}" FontSize="14"/>
</StackPanel>
</StackPanel>
</Grid>
</DataTemplate>
</Window.Resources>
<StackPanel Orientation="Horizontal" Margin="5">
<UserControl ContentTemplate="{StaticResource ResourceKey=carDetailViewTemplate}" Content="{Binding SelectedItem, ElementName=listBoxCars}"/>
<ListBox x:Name="listBoxCars" Width="180" Margin="5, 0" ItemTemplate="{StaticResource ResourceKey=carListItemViewTemplate}"/>
</StackPanel>
</Window>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
InitializeCarList();
}
private void InitializeCarList()
{
List<Car> carList = new List<Car>
{
new Car{Automaker = "Lamborghini", Name = "Diablo", Year = "1990", TopSpeed = "340"},
new Car{Automaker = "Lamborghini", Name = "Murcielago", Year = "2001", TopSpeed = "353"},
new Car{Automaker = "Lamborghini", Name = "Gallardo", Year = "2003", TopSpeed = "325"},
new Car{Automaker = "Lamborghini", Name = "Reventon", Year = "2008", TopSpeed = "356"}
};
this.listBoxCars.ItemsSource = carList;
}
}
本文出自 “墨池小样儿” 博客,请务必保留此出处http://306702895.blog.51cto.com/8366753/1628132
原文地址:http://306702895.blog.51cto.com/8366753/1628132