C# 如何在WPF中动态添加和定位复选框元素?
我开始制作一个WinForms应用程序来显示一个由4×4×4复选框组成的网格,表示现实生活中43个LED网格 这就是它现在的样子: 我想把它转换成一个WPF应用程序,这样我就可以使用WPF复选框的透明度选项,使复选框的非选定层[将有4层]略微透明,给它一种更真实的3D感觉 我是WPF新手,我尝试在主窗口中嵌套2个元素(例如,2个网格稍微重叠位置,大约20个像素,这样它们看起来是三维交错的),但它不允许我这样做,只允许我在原始网格中添加一个子网格 TLDR:我如何动态创建大量复选框,同时为它们提供绝对像素位置? 我当前正在使用的WinForms C#代码:C# 如何在WPF中动态添加和定位复选框元素?,c#,wpf,checkbox,C#,Wpf,Checkbox,我开始制作一个WinForms应用程序来显示一个由4×4×4复选框组成的网格,表示现实生活中43个LED网格 这就是它现在的样子: 我想把它转换成一个WPF应用程序,这样我就可以使用WPF复选框的透明度选项,使复选框的非选定层[将有4层]略微透明,给它一种更真实的3D感觉 我是WPF新手,我尝试在主窗口中嵌套2个元素(例如,2个网格稍微重叠位置,大约20个像素,这样它们看起来是三维交错的),但它不允许我这样做,只允许我在原始网格中添加一个子网格 TLDR:我如何动态创建大量复选框,同时为它们提
int间距=25;
int零=0;
对于(int z=1;z),考虑使用(或数据模板)来确定每个项目在viewmodel集合中的外观
例如:
<ListBox Width="400" Margin="10"
ItemsSource="{Binding Source={StaticResource myTodoList}}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Path=TaskName}" />
<TextBlock Text="{Binding Path=Description}"/>
<TextBlock Text="{Binding Path=Priority}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
我会使用多个UniformGrid
s在一个规则网格内堆叠在一起(因此它们会重叠)。每个UniformGrid的顶部和左侧边距会偏移特定的量
每个UniformGrid的项目源将绑定到视图模型上每个“层”的布尔属性列表中。您可以尝试此操作。在窗口内使用画布
<Window x:Name="myWindow1" x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<Canvas x:Name="canvas" >
</Canvas>
与Windows窗体中可用的位置不同,您可以使用边距设置位置
int spacing = 100;
int zero = 0;
for (int z = 1; z <= 4; z++)
{
List<string> zString = new List<string>();
for (int y = 1; y <= 4; y++)
{
for (int x = 1; x <= 4; x++)
{
int pixel_x = zero + ((x - 1) * spacing);
int pixel_y = zero + ((y - 1) * spacing);
CheckBox box = new CheckBox();
Canvas.SetLeft(box, pixel_x);
Canvas.SetTop(box, pixel_y);
this.canvas.Children.Add(box);
}
}
zero = zero + 50;
}
int间距=100;
int零=0;
对于(int z=1;z我将首先检查并确保您为此使用了适当的面板。最终,我可能会有4个包含一组复选框数据的数据对象集合,并使用ItemsControl
绘制每个集合。所有4个ItemsControl
都将有一个自定义的ItemsPanelTemplate
和ItemContainerStyle
,它们都放在一个单独的面板中,允许重叠的子项,如WPF中的Canvas
,而不是“动态创建”任何东西。相反,您定义一个适当的数据模型,一个适当的视图模型,然后使用XAML定义数据在屏幕上的呈现方式。这是一个重大的思维转变。作为记录,您编写的所有代码都必须删除。请遵循@Rachel的建议,使用ItemsControl
。这就是您在WPF中使用任何基于项的UI的方式。抱歉,这与WPF中所有已知的、公认的良好实践和模式背道而驰。-1.我曾试图使其与Windows窗体中的代码保持最接近。他的问题不是WPF中的绑定和最佳实践。他有两个问题,一个是关于主窗口中的一个孩子,另一个是关于位置。如果你绝对必须使用相同的winforms,那么de,我建议使用Canvas并设置Canvas.Top/Canvas.Left,而不是使用边距属性。我尝试了这一点,认为它很好,但问题是,复选框并不都有效,因为它们重叠了一些,阻止了其他复选框被单击。你有什么办法解决这个问题吗?使用this.Canvas.RegisterName(box.Name,box)然后您的发现应该会起作用。我按照您的建议做了,创建了一个主网格,并通过编程为每个z迭代添加了一个UniformGrid[4个].查看结果:我的问题是复选框在这里和那里重叠,并阻止其他复选框被选中。我按住ALT键,边框出现,看到了吗?你有什么建议吗?[我的代码在这里]这似乎是因为每个UniformGrid的宽度随着左边距的增加而变小。您应该将宽度设置为某个常量,或者将右边距设置为左边距的倒数。目标是使每个内部网格保持相同的宽度。我使用了此方法,使用纯MVVM完成网格线。如果您我对示例代码感兴趣,请告诉我。我将解决方案发布到bitBucket。它是用VB编写的,但应该很容易翻译。它生成以下输出。所有复选框都可以单击。
int spacing = 100;
int zero = 0;
for (int z = 1; z <= 4; z++)
{
List<string> zString = new List<string>();
for (int y = 1; y <= 4; y++)
{
for (int x = 1; x <= 4; x++)
{
int pixel_x = zero + ((x - 1) * spacing);
int pixel_y = zero + ((y - 1) * spacing);
CheckBox box = new CheckBox();
Canvas.SetLeft(box, pixel_x);
Canvas.SetTop(box, pixel_y);
this.canvas.Children.Add(box);
}
}
zero = zero + 50;
}