在我的WPF应用程序中,我使用包含ObservableCollection
的类的PointCollection
。此点集合用于为可观察集合中的每个项目绘制多边形。下面的代码显示了我如何使用模板绑定来绘制所有多边形:
<Grid>
<ItemsControl ItemsSource="{Binding GeoLines}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type vm:GeoPointsViewModel}">
<Polygon Stroke="LightSkyBlue" StrokeThickness="0.5" Opacity="0.8">
<Polygon.Style>
<Style TargetType="{x:Type Polygon}">
<Setter Property="Points">
<Setter.Value>
<MultiBinding Converter="{StaticResource pointMultiConverter}">
<Binding Path="ActualWidth" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type Canvas}}"/>
<Binding Path="ActualHeight" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type Canvas}}"/>
<Binding Path="Points"/>
</MultiBinding>
</Setter.Value>
</Setter>
<Setter Property="Fill" Value="#FF0A0A10"/>
</Style>
</Polygon.Style>
</Polygon>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
虽然效果很好,但性能并不高,因为每个多边形都是UIElement
,带有所有的铃声和口哨声。为了提高性能,我想使用占地面积较小的GeometryDrawing
。不幸的是,我不知道在这种情况下如何进行数据绑定。所以,我的问题是我如何使用GeometryDrawing
实现代码(或者比Shapes
重量轻的任何代码。)
答案 0 :(得分:2)
我不确定使用GeometryDrawing
是否可以显着改善性能,但是您可以通过以下方式实现它。结果可能看起来并不完全符合您的要求,因为StartPoint
的默认PathFigure
:
<DataTemplate DataType="{x:Type vm:GeoPointsViewModel}">
<Border>
<Border.Background>
<DrawingBrush>
<DrawingBrush.Drawing>
<GeometryDrawing Brush="Red">
<GeometryDrawing.Geometry>
<PathGeometry>
<PathFigure IsClosed="True">
<PolyLineSegment Points="{Binding Points}"/>
</PathFigure>
</PathGeometry>
</GeometryDrawing.Geometry>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
</Border.Background>
</Border>
</DataTemplate>
我使用简单的Red
画笔作为折线。如果需要,您还可以指定一些Pen
。请注意,多边形的效果可能与原始代码产生的效果不完全相同。我想你可能需要做一些调整才能做到正确。
答案 1 :(得分:1)
我最终使用后面的代码直接绘制视觉效果。这绕过了很多UI层并显着提高了性能。任何其他改进此代码的建议仍然受到欢迎。
private Brush geoBrush = (SolidColorBrush)(new BrushConverter().ConvertFrom("#FF0A0A10"));
private Pen geoPen = new Pen(Brushes.LightSkyBlue, 0.5);
private DropShadowEffect geoDropShadow = new DropShadowEffect
{
Color = Brushes.LightSteelBlue.Color,
BlurRadius = 8.0,
ShadowDepth = 0.0
};
private DrawingVisual GeoVisual = null;
private void UpdateGeoLines()
{
MapProjectionViewModel map = this.DataContext as MapProjectionViewModel;
if (map != null)
{
DrawingVisual visual = new DrawingVisual();
using (DrawingContext dc = visual.RenderOpen())
{
foreach (var item in map.GeoLines)
{
if (item.Points.Count > 1)
{
List<Point> points = new List<Point>();
foreach (var p in item.Points)
{
Point point = new Point(
p.X * canvas.ActualWidth,
p.Y * canvas.ActualHeight);
points.Add(point);
}
StreamGeometry geom = new StreamGeometry();
using (StreamGeometryContext gc = geom.Open())
{
Point p1 = points[0];
// Start new object, filled=true, closed=true
gc.BeginFigure(p1, true, true);
// isStroked=true, isSmoothJoin=true
gc.PolyLineTo(points, true, false);
}
geom.Freeze();
dc.DrawGeometry(geoBrush, geoPen, geom);
}
}
}
visual.Effect = geoDropShadow;
visual.Opacity = 0.8;
canvas.Visuals.Remove(GeoVisual);
canvas.Visuals.Add(visual);
GeoVisual = visual;
}
}