我知道这个问题已经得到解答,但 HighCore 所谈论的内容(即不要在代码中操纵 UI 元素)不能足够有力地说明。要正确执行此操作,您应该创建一个类来封装您要显示的数据:
public class Widget : ViewModelBase
{
private double _X;
public double X
{
get { return _X;}
set { _X = value; RaisePropertyChanged(() => this.X); }
}
private double _Y;
public double Y
{
get { return _Y;}
set { _Y = value; RaisePropertyChanged(() => this.Y); }
}
private double _Width;
public double Width
{
get { return _Width;}
set { _Width = value; RaisePropertyChanged(() => this.Width); }
}
private double _Height;
public double Height
{
get { return _Height;}
set { _Height = value; RaisePropertyChanged(() => this.Height); }
}
private System.Windows.Media.Color _Color;
public System.Windows.Media.Color Color
{
get { return _Color;}
set { _Color = value; RaisePropertyChanged(() => this.Color); }
}
}
为每个参数创建这些依赖属性有点烦人,我使用内置的代码片段管理器为我创建一个 sn-p,这样我就不必每次都输入整个内容。接下来,您要创建一个数组并将它们放在某个视图模型中,那是生成椭圆的逻辑应该去的地方:
public MyViewModel()
{
for (int y = 0; y < 10; y++)
for (int x = 0; x < 10; x++)
this.Items.Add(new Widget {
X = x * 20,
Y = y * 20,
Width = 10,
Height = 10,
Color = Color.FromArgb(255, (byte)(x * 20), (byte)(y * 20), 0)
});
}
然后,您可以将 MyViewModel 的一个实例设置为包含您的画布的窗口的数据上下文。剩下的就是松散绑定到此视图模型的 XAML,您希望将项目列表呈现到画布上,以便使用 ItemsControl 并将默认项目面板替换为画布:
<ItemsControl ItemsSource="{Binding Items}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Ellipse Width="{Binding Width}" Height="{Binding Height}">
<Ellipse.Stroke>
<SolidColorBrush Color="{Binding Color}" />
</Ellipse.Stroke>
</Ellipse>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Canvas.Left" Value="{Binding X}" />
<Setter Property="Canvas.Top" Value="{Binding Y}" />
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
结果如下:
您现在将前端数据绑定到您的视图模型,因此您可以添加/删除项目或更改单个属性等,并且更改将传播。您还可以对您的逻辑进行单元测试,而无需实际创建视图控件。