WPF 如何通过代码创建一个包含 Canvas 作为内容的 DataTemplate?
WPF How to Create a DataTemplate Which has Canvas As Content By Code?
我有 XAML 定义的数据模板如下:
<DataTemplate x:Key="PointPushPinItemTemplate">
<mapControl:MapItem mapControl:MapPanel.Location="{Binding}" >
<Canvas>
<Path StrokeThickness="2" Fill="Aqua">
<Path.Data>
<EllipseGeometry RadiusX="10" RadiusY="10"/>
</Path.Data>
</Path>
</Canvas>
</mapControl:MapItem>
</DataTemplate>
我使用下面的代码创建它,但失败了:
private DataTemplate PushPinPointDataTemplate()
{
var pointItemFactory = new FrameworkElementFactory(typeof(MapItem));
pointItemFactory.SetValue(MapPanel.LocationProperty, new Binding());
var pointCanvas = new Canvas();
pointCanvas.Children.Add(new Path
{
StrokeThickness = 2.0,
Fill = new SolidColorBrush(Colors.Yellow),
Data = new EllipseGeometry {RadiusX = 3, RadiusY = 3}
});
//below line always throw exception that FrameworkElementFactory.SetValue can't set a visual value
pointItemFactory.SetValue(MapItem.ContentProperty, pointCanvas);
return new DataTemplate
{
DataType = typeof(Location),
VisualTree = pointItemFactory
};
}
如何实现?以前,我在没有 Canvas 的情况下实现了这一点,但对于这种情况,Canvas 是内容控件的内容。
ps: mapControl:MapItem 是继承自 ListBoxItem 的 UI 元素
mapControl:MapPanel.位置是附件属性
您还需要为 Canvas
和 Path
创建工厂:
private DataTemplate PushPinPointDataTemplate()
{
var pointItemFactory = new FrameworkElementFactory(typeof(MapItem));
pointItemFactory.SetValue(MapPanel.LocationProperty, new Binding("."));
var pathFactory = new FrameworkElementFactory(typeof(Path));
pathFactory.SetValue(Path.StrokeThicknessProperty, 2.0);
pathFactory.SetValue(Path.FillProperty, Brushes.Yellow);
pathFactory.SetValue(Path.DataProperty, new EllipseGeometry { RadiusX = 3, RadiusY = 3 });
var pointCanvasFactory = new FrameworkElementFactory(typeof(Canvas));
pointCanvasFactory.AppendChild(pathFactory);
pointItemFactory.AppendChild(pointCanvasFactory);
return new DataTemplate
{
DataType = typeof(Location),
VisualTree = pointItemFactory
};
}
请注意,使用 FrameworkElementFactory
以编程方式创建模板是一种已弃用的方法:https://msdn.microsoft.com/en-us/library/system.windows.frameworkelementfactory(v=vs.110).aspx。
The recommended way to programmatically create a template is to load XAML from a string
or a memory stream using the Load
method of the XamlReader
class.
我有 XAML 定义的数据模板如下:
<DataTemplate x:Key="PointPushPinItemTemplate">
<mapControl:MapItem mapControl:MapPanel.Location="{Binding}" >
<Canvas>
<Path StrokeThickness="2" Fill="Aqua">
<Path.Data>
<EllipseGeometry RadiusX="10" RadiusY="10"/>
</Path.Data>
</Path>
</Canvas>
</mapControl:MapItem>
</DataTemplate>
我使用下面的代码创建它,但失败了:
private DataTemplate PushPinPointDataTemplate()
{
var pointItemFactory = new FrameworkElementFactory(typeof(MapItem));
pointItemFactory.SetValue(MapPanel.LocationProperty, new Binding());
var pointCanvas = new Canvas();
pointCanvas.Children.Add(new Path
{
StrokeThickness = 2.0,
Fill = new SolidColorBrush(Colors.Yellow),
Data = new EllipseGeometry {RadiusX = 3, RadiusY = 3}
});
//below line always throw exception that FrameworkElementFactory.SetValue can't set a visual value
pointItemFactory.SetValue(MapItem.ContentProperty, pointCanvas);
return new DataTemplate
{
DataType = typeof(Location),
VisualTree = pointItemFactory
};
}
如何实现?以前,我在没有 Canvas 的情况下实现了这一点,但对于这种情况,Canvas 是内容控件的内容。 ps: mapControl:MapItem 是继承自 ListBoxItem 的 UI 元素 mapControl:MapPanel.位置是附件属性
您还需要为 Canvas
和 Path
创建工厂:
private DataTemplate PushPinPointDataTemplate()
{
var pointItemFactory = new FrameworkElementFactory(typeof(MapItem));
pointItemFactory.SetValue(MapPanel.LocationProperty, new Binding("."));
var pathFactory = new FrameworkElementFactory(typeof(Path));
pathFactory.SetValue(Path.StrokeThicknessProperty, 2.0);
pathFactory.SetValue(Path.FillProperty, Brushes.Yellow);
pathFactory.SetValue(Path.DataProperty, new EllipseGeometry { RadiusX = 3, RadiusY = 3 });
var pointCanvasFactory = new FrameworkElementFactory(typeof(Canvas));
pointCanvasFactory.AppendChild(pathFactory);
pointItemFactory.AppendChild(pointCanvasFactory);
return new DataTemplate
{
DataType = typeof(Location),
VisualTree = pointItemFactory
};
}
请注意,使用 FrameworkElementFactory
以编程方式创建模板是一种已弃用的方法:https://msdn.microsoft.com/en-us/library/system.windows.frameworkelementfactory(v=vs.110).aspx。
The recommended way to programmatically create a template is to load XAML from a
string
or a memory stream using theLoad
method of theXamlReader
class.