我正在尝试设置将用于Line(System.Windows.Shapes.Line)对象的WPF DataTemplate .
从默认的.NET 4 WPF应用程序,我将我的Window xaml设置为:
<Window x:Class="WpfTestDataTemplates.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<DataTemplate DataType="{x:Type system:String}" >
<TextBlock>It's a string</TextBlock>
</DataTemplate>
<DataTemplate DataType="{x:Type Line}" >
<TextBlock>It's a line</TextBlock>
</DataTemplate>
</Window.Resources>
<ListView ItemsSource="{Binding MyItems}" />
</Window>
Run Code Online (Sandbox Code Playgroud)
而背后的代码是:
using System.Collections.Generic;
using System.Windows;
using System.Windows.Shapes;
namespace WpfTestDataTemplates
{
public partial class MainWindow : Window
{
public List<object> MyItems {get; set; }
public MainWindow()
{
InitializeComponent();
DataContext = this;
MyItems = new List<object>();
MyItems.Add("The first string");
MyItems.Add(new Line { X1 = 0, Y1 = 0, X2 = 5, Y2 = 5 });
MyItems.Add("The second string");
MyItems.Add(new Rectangle { Height = 5, Width = 15 });
MyItems.Add(42);
}
}
}
Run Code Online (Sandbox Code Playgroud)
生成的窗口如下所示:

我希望第二个条目读取:它是一行,但似乎Line找不到该类型的DataTemplate .对于没有显式DataTemplate的类型,我希望默认呈现是对象的.ToString()成员,但这不是正在发生的事情.所以我希望第四个条目是:System.Windows.Shapes.Rectangle
为什么{x:Type Line}不能识别类型,以及哪些DataTemplate应用于Shape对象?
ADataTemplate是您用来将 UI 放置在不是其本身UIElements并且没有在屏幕上呈现自身的概念的数据对象上的东西。Line然而RectangleUIElements 是这样的——它们知道如何渲染自己,并且不需要 DataTemplate 来告诉它们如何渲染。
如果你给你的直线和矩形一些颜色,你会发现它们忽略了善意的数据模板并在列表中显示为直线和矩形:
MyItems.Add(new Line { X1 = 0, Y1 = 0, X2 = 5, Y2 = 5,
Stroke = Brushes.Lime, StrokeThickness = 2 });
...
MyItems.Add(new Rectangle { Height = 5, Width = 15, Fill = Brushes.Blue });
Run Code Online (Sandbox Code Playgroud)

要更改 UIElements 的外观,您通常会使用Style(如果它是FrameworkElement)和/或ControlTemplate(如果它是Control)。
编辑:
Line如果您有自己的数据类来表示一条线(我们称之为),而不是LineData,则可以使用 DataTemplate 以任何您想要的方式呈现该类:
public class LineData
{
public LineData(Point start, Point end)
{
this.Start = start;
this.End = end;
}
public Point Start { get; private set; }
public Point End { get; private set; }
public double XLength
{
get { return this.End.X - this.Start.X; }
}
public double YLength
{
get { return this.End.Y - this.Start.Y; }
}
}
...
MyItems.Add(new LineData(new Point(10, 10), new Point(60, 30)));
Run Code Online (Sandbox Code Playgroud)
..和数据模板..
<DataTemplate DataType="{x:Type vm:LineData}" >
<StackPanel Orientation="Horizontal" SnapsToDevicePixels="True" >
<TextBlock>It's a line:</TextBlock>
<Grid>
<Rectangle Stroke="Black" StrokeThickness="1"
Width="{Binding Path=XLength}" Height="{Binding Path=YLength}" />
<Line Stroke="Red" StrokeThickness="2"
X1="{Binding Path=Start.X}" Y1="{Binding Path=Start.Y}"
X2="{Binding Path=End.X}" Y2="{Binding Path=End.Y}" />
</Grid>
</StackPanel>
</DataTemplate>
Run Code Online (Sandbox Code Playgroud)
..给我们:
