C# 在ItemsControl中使用GeometryDrawing
在我的WPF应用程序中,我使用了一个类的C# 在ItemsControl中使用GeometryDrawing,c#,wpf,performance,data-binding,itemscontrol,C#,Wpf,Performance,Data Binding,Itemscontrol,在我的WPF应用程序中,我使用了一个类的可观测集合,该类包含点集合。此点集合用于为可观察集合中的每个项目绘制多边形。下面的代码展示了如何使用模板绑定绘制所有多边形: <Grid> <ItemsControl ItemsSource="{Binding GeoLines}"> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <C
可观测集合
,该类包含点集合
。此点集合用于为可观察集合中的每个项目绘制多边形。下面的代码展示了如何使用模板绑定绘制所有多边形:
<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>
虽然它工作得很好,但性能并不好,因为每个多边形都是一个
ui元素
,有着所有的铃铛和哨子。为了提高性能,我想使用占用空间较小的GeometryDrawing
。不幸的是,我不知道在这种情况下如何进行数据绑定。因此,我的问题是如何使用GeometryDrawing
(或者比Shapes
更轻的东西)实现代码。我不确定使用GeometryDrawing
是否可以显著提高性能,但下面是如何实现它。结果可能不完全符合您的要求,这是因为PathFigure
的默认StartPoint
:
<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>
我对多段线使用了一个简单的
红色
。如果需要,还可以指定一些笔。请注意,多边形的效果可能与原始代码产生的效果不完全相同。我想你可能需要做更多的调整才能把它做好。我最终使用代码隐藏直接绘制视觉效果。这绕过了许多UI层,显著提高了性能。任何其他改进此代码的建议仍然是受欢迎的
,这将更加合乎逻辑。@ RASMATASH,而不是使用<代码>刷< /代码>,尝试添加一些<代码>笔<代码> > <代码>几何图形< /代码>,它将连接<代码> PooToCube < /Code >(每个项目)中的所有点。结果当然应该非常类似于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; } }
谢谢。不幸的是,这不起作用。即使这样,它也会为每个项目创建一个路径几何体,这正是我想要避免的。我设法用private Brush geoBrush=(SolidColorBrush)(新的BrushConverter().ConvertFrom(“#ff0a0a10a10”); private Pen geoPen=新笔(画笔。浅天蓝,0.5); 私有DropShadowEffect geoDropShadow=新DropShadowEffect { 颜色=画笔。LightSteelBlue.Color, 半径=8.0, 阴影深度=0.0 }; 私有DrawingVisualGeoVisualic=null; 私有void updategolines() { MapProjectionViewModel map=this.DataContext作为MapProjectionViewModel; if(map!=null) { DrawingVisual=新建DrawingVisual(); 使用(DrawingContext dc=visual.renderropen()) { foreach(map.GeoLines中的变量项) { 如果(item.Points.Count>1) { 列表点=新列表(); foreach(项目点中的var p) { 点=新点( p、 X*canvas.ActualWidth, p、 Y*画布实际高度); 点。添加(点); } StreamGeometry geom=新的StreamGeometry(); 使用(StreamGeometryContext gc=geom.Open()) { 点p1=点[0]; //启动新对象,填充=真,关闭=真 gc.BeginFigure(p1,true,true); //isStroked=true,isSmoothJoin=true gc.PolyLineTo(点,真,假); } geom.Freeze(); dc.绘图几何(geoBrush、geoPen、geom); } } } visual.Effect=geoDropShadow; 视觉不透明度=0.8; canvas.Visuals.Remove(地理视觉); canvas.Visuals.Add(可视); 地理视觉=视觉; } }
解决了这个问题(参见我的答案)。@rashmatash代码没有编译?您所说的为每个项目创建一个路径几何体是什么意思?据我所知,您的原始代码每个项目也只有一个多边形。这段代码的工作原理应该至少与您的原始代码几乎相同(因此我说您可能需要更多的调整)。如果您想使用代码,请考虑绑定DrawingVisual
背景
,并使用某种代码>转换器多边形(我们甚至在这里设置了
)。IsClosed=“True”
是如何调用的?@VRage:我已经没有代码了,但我相信xaml只是一个updategolines()
,有一个空的UserControl
,它是Canvas
中的updategolines()
变量。然后,每当需要更新画布时,只需清除画布并在事件处理程序中调用Canvas
。希望有帮助。updategolines()