C# 在WPF中高效地绘制二维网格
这是一个Windows窗体程序,它绘制了一个由随机着色为黑色或红色的正方形组成的二维网格:C# 在WPF中高效地绘制二维网格,c#,wpf,winforms,C#,Wpf,Winforms,这是一个Windows窗体程序,它绘制了一个由随机着色为黑色或红色的正方形组成的二维网格: using System; using System.Drawing; using System.Windows.Forms; namespace Forms_Panel_Random_Squares { public partial class Form1 : Form { public Form1() { InitializeC
using System;
using System.Drawing;
using System.Windows.Forms;
namespace Forms_Panel_Random_Squares
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Width = 350;
Height = 350;
var panel = new Panel() { Dock = DockStyle.Fill };
Controls.Add(panel);
var random = new Random();
panel.Paint += (sender, e) =>
{
e.Graphics.Clear(Color.Black);
for (int i = 0; i < 30; i++)
for (int j = 0; j < 30; j++)
{
if (random.Next(2) == 1)
e.Graphics.FillRectangle(
new SolidBrush(Color.Red),
i * 10,
j * 10,
10,
10);
}
};
}
}
}
由于世界上的每个单元都有一个矩形
对象的开销,WPF版本的内存效率似乎要低得多
有没有一种方法可以像表单版本那样高效地编写这个程序?或者没有办法创建所有这些
矩形
对象吗?可以混合使用WPF和表单。因此,可以通过WindowsFormsHost
将面板嵌入到WPF窗口中,而不是执行纯表单路线。下面是一个WPF程序,它演示了这一点:
using System;
using System.Windows;
using System.Windows.Forms.Integration;
using System.Drawing;
namespace WindowsFormsHost_Random_Squares
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Width = 350;
Height = 350;
Random random = new Random();
var windowsFormsHost = new WindowsFormsHost();
Content = windowsFormsHost;
var panel = new System.Windows.Forms.Panel()
{ Dock = System.Windows.Forms.DockStyle.Fill };
windowsFormsHost.Child = panel;
panel.Paint += (sender, e) =>
{
e.Graphics.Clear(System.Drawing.Color.Black);
for (int i = 0; i < 30; i++)
for (int j = 0; j < 30; j++)
{
if (random.Next(2) == 1)
e.Graphics.FillRectangle(
new SolidBrush(System.Drawing.Color.Red),
i * 10,
j * 10,
10,
10);
}
};
}
}
}
使用系统;
使用System.Windows;
使用System.Windows.Forms.Integration;
使用系统图;
命名空间WindowsFormsHost\u随机方
{
公共部分类主窗口:窗口
{
公共主窗口()
{
初始化组件();
宽度=350;
高度=350;
随机=新随机();
var windowsFormsHost=新windowsFormsHost();
Content=windowsFormsHost;
var panel=new System.Windows.Forms.panel()
{Dock=System.Windows.Forms.DockStyle.Fill};
windowsFormsHost.Child=面板;
panel.Paint+=(发送器,e)=>
{
e、 图形。清晰(系统。绘图。颜色。黑色);
对于(int i=0;i<30;i++)
对于(int j=0;j<30;j++)
{
if(随机下一个(2)==1)
e、 图形填充矩形(
新的SolidBrush(系统、图纸、颜色、红色),
i*10,
j*10,
10,
10);
}
};
}
}
}
这里有一个纯WPF解决方案<代码>框架元素是子类。这个新的子类(DrawingVisualElement
)公开了一个可用于绘制的DrawingVisualElement
对象
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace DrawingVisualSample
{
public class DrawingVisualElement : FrameworkElement
{
private VisualCollection _children;
public DrawingVisual drawingVisual;
public DrawingVisualElement()
{
_children = new VisualCollection(this);
drawingVisual = new DrawingVisual();
_children.Add(drawingVisual);
}
protected override int VisualChildrenCount
{
get { return _children.Count; }
}
protected override Visual GetVisualChild(int index)
{
if (index < 0 || index >= _children.Count)
throw new ArgumentOutOfRangeException();
return _children[index];
}
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Width = 350;
Height = 350;
var stackPanel = new StackPanel();
Content = stackPanel;
var drawingVisualElement = new DrawingVisualElement();
stackPanel.Children.Add(drawingVisualElement);
var drawingContext = drawingVisualElement.drawingVisual.RenderOpen();
var random = new Random();
for (int i = 0; i < 30; i++)
for (int j = 0; j < 30; j++)
drawingContext.DrawRectangle(
random.Next(2) == 0 ? Brushes.Black : Brushes.Red,
(Pen)null,
new Rect(i * 10, j * 10, 10, 10));
drawingContext.Close();
}
}
}
使用系统;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Media;
命名空间DrawingVisualSample
{
公共类DrawingVisualElement:FrameworkElement
{
儿童私人视觉采集;
公共绘图视觉绘图视觉绘图;
公共绘图VisualElement()
{
_儿童=新的视觉集合(本);
drawingVisual=新drawingVisual();
_添加(drawingVisual);
}
受保护的重写int VisualChildrenCount
{
获取{return\u children.Count;}
}
受保护的重写Visual GetVisualChild(int索引)
{
如果(索引<0 | |索引>=_children.Count)
抛出新ArgumentOutOfRangeException();
返回子项[索引];
}
}
公共部分类主窗口:窗口
{
公共主窗口()
{
初始化组件();
宽度=350;
高度=350;
var stackPanel=新的stackPanel();
内容=stackPanel;
var drawingVisualElement=新的drawingVisualElement();
stackPanel.Children.Add(drawingVisualElement);
var drawingContext=drawingVisualElement.drawingVisual.RenderRopen();
var random=新的random();
对于(int i=0;i<30;i++)
对于(int j=0;j<30;j++)
drawingContext.DrawRectangle(
随机。下一(2)=0?画笔。黑色:画笔。红色,
(笔)空,
新的Rect(i*10,j*10,10,10));
drawingContext.Close();
}
}
}
您是想要对象还是仅仅改变背景颜色,是否需要使用画布而不是网格?我想在二维数组中渲染状态。因此,我不需要视图级别的重对象表示suggests@MarkHall谢谢你给我这个答案的指针!我添加了一个演示如何使用DrawingVisual
和DrawingContext
。
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace DrawingVisualSample
{
public class DrawingVisualElement : FrameworkElement
{
private VisualCollection _children;
public DrawingVisual drawingVisual;
public DrawingVisualElement()
{
_children = new VisualCollection(this);
drawingVisual = new DrawingVisual();
_children.Add(drawingVisual);
}
protected override int VisualChildrenCount
{
get { return _children.Count; }
}
protected override Visual GetVisualChild(int index)
{
if (index < 0 || index >= _children.Count)
throw new ArgumentOutOfRangeException();
return _children[index];
}
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Width = 350;
Height = 350;
var stackPanel = new StackPanel();
Content = stackPanel;
var drawingVisualElement = new DrawingVisualElement();
stackPanel.Children.Add(drawingVisualElement);
var drawingContext = drawingVisualElement.drawingVisual.RenderOpen();
var random = new Random();
for (int i = 0; i < 30; i++)
for (int j = 0; j < 30; j++)
drawingContext.DrawRectangle(
random.Next(2) == 0 ? Brushes.Black : Brushes.Red,
(Pen)null,
new Rect(i * 10, j * 10, 10, 10));
drawingContext.Close();
}
}
}