C# 是否可以将Windows窗体中的表用作矩阵?

C# 是否可以将Windows窗体中的表用作矩阵?,c#,winforms,matrix,C#,Winforms,Matrix,我正在尝试创建一个简单的6X8单元矩阵,用户可以在其中单击一个单元并将其打开或关闭,黑色或白色。我一直在试验windows窗体控件并查看数据网格控件,但到目前为止,我还看不到使用Winforms工具箱中的任何内容来创建矩阵的方法 我创建了这个表,但看不到单独设置每个单元格样式的方法,也看不到为每个单元格使用onclick事件的方法。这可能吗?如果不可能,还有其他方法吗?您最好在运行时使用一组标签: List<Label> lables=new List<Label>();

我正在尝试创建一个简单的6X8单元矩阵,用户可以在其中单击一个单元并将其打开或关闭,黑色或白色。我一直在试验windows窗体控件并查看数据网格控件,但到目前为止,我还看不到使用Winforms工具箱中的任何内容来创建矩阵的方法


我创建了这个表,但看不到单独设置每个单元格样式的方法,也看不到为每个单元格使用onclick事件的方法。这可能吗?如果不可能,还有其他方法吗?

您最好在运行时使用一组标签:

List<Label> lables=new List<Label>();



var a = new Label();
labels.Add(a);
//... set positions and sizes
a.AutoSize=False;

this.Controls.Add(a);
列表标签=新列表();
var a=新标签();
标签.加入(a);
//... 设置位置和大小
a、 AutoSize=False;
本.控件.添加(a);

有了它,您以后可以为标签数组中的每个标签编制索引,以匹配行/列的位置。

我认为您可以在WinForms中使用DataGridView控件。您可以设置所需的列数和行数。例如,对于列

m_Grid.ColumnCount = 5;

m_Grid.Rows.Add();
您可以处理CellClick、CellDoumleClick或其他事件,并在其字段中使用参数DataGridViewCellEventArgs。比如说,

m_Grid.Rows[e.RowIndex].Cells[e.ColumnIndex].Style.BackColor = Color.Red;

下面是一个在运行时创建标签的解决方案。您需要一个面板来承载您的“矩阵”和一个按钮,所有这些都带有默认名称。该按钮将在单击时绘制棋盘格,您可以通过单击每个单元格来翻转颜色

public partial class Form1 : Form
{
  public Form1()
  {
    InitializeComponent();
  }

  const int RowCount = 6;
  const int ColumnCount = 8;
  private void button1_Click(System.Object sender, System.EventArgs e)
  {
    for (int i = 0; i < RowCount; i++)
    {
      for (int j = 0; j < ColumnCount; j++)
      {
        Label lbl = new Label();
        lbl.Size = new Size(20, 20);
        lbl.Location = new Point(i * 20, j * 20);
        lbl.BackColor = (i + j) % 2 == 0 ? Color.Black : Color.White;
        lbl.Click += lbl_Click;
        panel1.Controls.Add(lbl);
      }
    }

    MessageBox.Show(CountCellsOfColor(Color.Black).ToString());
  }

  private int CountCellsOfColor(Color color)
  {
    int count = 0;
    foreach (Label lbl in panel1.Controls.OfType<Label>())
    {                
      if (lbl.BackColor == color) count += 1;
    }
    return count;
  }

  private void lbl_Click(object sender, System.EventArgs e)
  {
    Label lbl = (Label)sender;
    Color color = lbl.BackColor;
    if (color == System.Drawing.Color.Black)
    {
      color = System.Drawing.Color.White;
    }
    else
    {
      color = System.Drawing.Color.Black;
    }
    lbl.BackColor = color;
  }   
}     

以下是我的WPF方法:

<Window x:Class="WpfApplication4.Window13"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window13" Height="300" Width="300">
    <ItemsControl ItemsSource="{Binding}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <UniformGrid Rows="8" Columns="6" IsItemsHost="True"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <DataTemplate.Resources>
                    <Storyboard x:Key="ToBlack" TargetName="RctFill" Duration="00:00:00.5">
                        <ColorAnimation From="White" To="Black" Duration="00:00:00.5" Storyboard.TargetProperty="Color"/>
                    </Storyboard>
                    <Storyboard x:Key="ToWhite" TargetName="RctFill" Duration="00:00:00.5">
                        <ColorAnimation From="Black" To="White" Duration="00:00:00.5"  Storyboard.TargetProperty="Color"/>
                    </Storyboard>
                </DataTemplate.Resources>
                <Button Command="{Binding ToggleCommand}">
                    <Button.Template>
                        <ControlTemplate>
                            <Rectangle Stroke="Black" StrokeThickness="1" x:Name="Rct">
                                <Rectangle.Fill>
                                    <SolidColorBrush Color="White" x:Name="RctFill"/>
                                </Rectangle.Fill>
                            </Rectangle>
                            <ControlTemplate.Triggers>
                                <DataTrigger Binding="{Binding State}" Value="True">
                                    <DataTrigger.EnterActions>
                                        <BeginStoryboard Storyboard="{StaticResource ToBlack}"/>
                                    </DataTrigger.EnterActions>
                                    <DataTrigger.ExitActions>
                                        <BeginStoryboard Storyboard="{StaticResource ToWhite}"/>
                                    </DataTrigger.ExitActions>
                                </DataTrigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Button.Template>
                </Button>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Window>
我正在使用来自WPFTutorial.Net的

只需将我的代码复制并粘贴到
文件->新项目->WPF应用程序中
,然后自己查看结果。您还需要我链接到的
DelegateCommand
定义

从黑色到白色的过渡是动画化的,您还可以扩展我的示例以动画化其他属性,在每个单元格中放置您想要的任何UI。此外,您将认识到这是完全独立于分辨率的,调整窗口大小也会调整
UniformGrid
的大小,从而调整所有网格单元的大小


如果您需要将其放入winforms应用程序中,您需要使用

如果您感兴趣,我可以为您的问题提供一个干净、美观、生动、基于WPF的解决方案。然后,您可以使用
ElementHost
将其集成到现有的winforms应用程序中。我会创建自己的usercontrol来实现这一点,或者更糟糕的是,只需使用picturebox。你将和一个像桌子一样沉重的东西战斗很久,你很可能也会失败…@HighCore如果你想提供一个解决方案,那么就提供一个解决方案,并将其作为答案发布。没有必要发表评论说你可以写一个解决方案;这不是其他人需要知道的。谢谢大家!我的第一个想法是使用picture pox并使用坐标将其拆分为多个部分,这是否可能,我希望如此。@HighCore您需要解释您的WPF解决方案如何能够被winform项目使用,如果您选择使用它,我并不是说没有人会批评你为winform问题提供WPF解决方案,但事实上,你可以提供答案是没有帮助的。现在,如果你想问一个问题,比如“提供一个可以集成到winform项目中的WPF解决方案是否可以接受?”那么这不再是一个无用的评论,而是一个澄清问题,它可以帮助你帮助OP,并且是一个适当的评论。谢谢Felice,但我不确定我是否知道如何使用标签来实现这一点,是否可以通过单击标签来设置这些标签的颜色?如果需要,只读texblock将是相同的。只需在每个标签上附加一个适当的事件处理程序。我在一个数独游戏实现-1上就是这么做的,因为你的解决方案没有OP要求的黑/白效果。而且,我在你的答案中没有看到6 x 8的网格。这看起来很棒,符合我希望做的,如果你能将其转换,那将非常棒,因为我从未使用过VB。非常感谢。很棒的Neolisk,我现在就试试这个,虽然看起来很棒!干杯@deucalion0:一切都是在运行时创建的,由单击按钮触发。你按按钮了吗?如果您不喜欢这种行为,您可以在
初始化组件后将该代码放入
子新建
;或
Form\u Load
,或根据需要。@deucalion0:当然,只需遍历所有标签,并计算具有所需背景色的标签。请参阅我的编辑以了解如何操作。@deucalion0:您可以创建一个2D数组作为类级变量,并在其中存储标签。然后通过行/列索引[i,j]访问标签应该非常简单。感谢HighCore,我将研究并尝试实现它,我感谢您的帮助和努力@FelicePollano后面的代码仅为设置
窗口的DataContext的1行。缺乏良好实践的地方在哪里?我仍然对你的答案感兴趣,我确实选择了另一个问题作为我的答案,但我仍然会在有时间时尝试你的解决方案,谢谢你的回答。
<Window x:Class="WpfApplication4.Window13"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window13" Height="300" Width="300">
    <ItemsControl ItemsSource="{Binding}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <UniformGrid Rows="8" Columns="6" IsItemsHost="True"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <DataTemplate.Resources>
                    <Storyboard x:Key="ToBlack" TargetName="RctFill" Duration="00:00:00.5">
                        <ColorAnimation From="White" To="Black" Duration="00:00:00.5" Storyboard.TargetProperty="Color"/>
                    </Storyboard>
                    <Storyboard x:Key="ToWhite" TargetName="RctFill" Duration="00:00:00.5">
                        <ColorAnimation From="Black" To="White" Duration="00:00:00.5"  Storyboard.TargetProperty="Color"/>
                    </Storyboard>
                </DataTemplate.Resources>
                <Button Command="{Binding ToggleCommand}">
                    <Button.Template>
                        <ControlTemplate>
                            <Rectangle Stroke="Black" StrokeThickness="1" x:Name="Rct">
                                <Rectangle.Fill>
                                    <SolidColorBrush Color="White" x:Name="RctFill"/>
                                </Rectangle.Fill>
                            </Rectangle>
                            <ControlTemplate.Triggers>
                                <DataTrigger Binding="{Binding State}" Value="True">
                                    <DataTrigger.EnterActions>
                                        <BeginStoryboard Storyboard="{StaticResource ToBlack}"/>
                                    </DataTrigger.EnterActions>
                                    <DataTrigger.ExitActions>
                                        <BeginStoryboard Storyboard="{StaticResource ToWhite}"/>
                                    </DataTrigger.ExitActions>
                                </DataTrigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Button.Template>
                </Button>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Window>
using System;
using System.Linq;
using System.Windows;
using System.ComponentModel;

namespace WpfApplication4
{
    public partial class Window13 : Window
    {
        public Window13()
        {
            var rnd = new Random();
            InitializeComponent();
            DataContext = Enumerable.Range(0, 48).Select(x => new Square() {State = rnd.Next(0,5) > 3});
        }
    }

    public class Square:INotifyPropertyChanged
    {
        private bool _state;
        public bool State
        {
            get { return _state; }
            set
            {
                _state = value;
                NotifyPropertyChanged("State");
            }
        }

        private DelegateCommand _toggleCommand;
        public DelegateCommand ToggleCommand
        {
            get { return _toggleCommand ?? (_toggleCommand = new DelegateCommand(x => State = !State)); }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}