【问题标题】:Create a custom DataGrid's ItemsSource创建自定义 DataGrid 的 ItemsSource
【发布时间】:2012-05-25 20:15:20
【问题描述】:

我正在使用 DataGrids,但我正在努力绑定我的数据,因为列数取决于必须显示的信息。

所以,我试图做的是创建一个包含我在某个时候需要的所有列和行的对象,并将该对象绑定到ItemsSource 属性。由于我在 WindowsForms 中使用过 DataGridViews,因此我想到了这样的事情:

DataTable myTable = new DataTable();

DataColumn col01 = new DataColumn("col 01");
myTable.Columns.Add(col01);
DataColumn col02 = new DataColumn("col 02");
myTable.Columns.Add(col02);

DataRow row = myTable.NewRow();
row[0] = "data01";
row[1] = "data02";
myTable.Rows.Add(row);

row = myTable.NewRow();
row[0] = "data01";
row[1] = "data02";
myTable.Rows.Add(row);

但我无法在 WPF 中找到一种方法来做同样的事情,因为我需要一些列作为 DataGridComboBoxColumns。

其实我在这个网站上读过很多关于它的帖子,但没有一个对我有帮助。我真的迷路了。

谁能帮助我?我只需要能够创建一个可能包含 DataGridTextColumns 或 `DataGridComboBoxColumns 等的表,以便将此最终对象绑定到 DataGrid 的 ItemsSource 属性。

希望有人可以帮助我。

【问题讨论】:

    标签: c# wpf data-binding datagrid


    【解决方案1】:

    好吧,让我试着举一个和你的需求相似的例子

    假设我们使用这个类:

    public class MyObject
    {
       public int MyID;
       public string MyString;
       public ICommand MyCommand;
    }
    

    我们愿意显示DataGrid 列出 ID,并在第二列中显示Button,属性MyString 作为内容,单击时会启动ICommand MyCommand无论您想要什么,都会在新窗口中打开。

    这是您在视图方面应该拥有的:

        <DataGrid ItemsSource="{Binding MyList}" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Header="ID" Binding="{Binding MyID}" />
                <DataGridTemplateColumn Header="Buttons">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Button Content="{Binding MyString}" Command="{Binding MyCommand}" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    

    这将显示DataGrid 获取名为“MyList”的IEnumerable&lt;MyObject&gt; 中的所有内容,并显示之前定义的两列。

    现在,如果您需要定义命令。 首先,我建议您阅读this introductory link to MVVM 并参加RelayCommand 课程(这就是我们将用于解决您的问题)

    所以,在你的ViewModel 中,定义MyList 的那个,是你应该如何定义一些有用的对象:

    public ObservableCollection<MyObject> MyList { get; set; }
    
    // blah blah blah
    
    public void InitializeMyList()
    {
      MyList = new ObservableCollection<MyObject>();
      for (int i = 0; i < 5; i++)
      {
        MyList.Add(InitializeMyObject(i));
      }
    }
    
    public MyObject InitializeMyObject(int i)
    {
      MyObject theObject = new MyObject();
      theObject.MyID = i;
      theObject.MyString = "The object " + i;
      theObject.MyCommand = new RelayCommand(param =< this.ShowWindow(i));
      return theObject
    }
    
    private void ShowWindow(int i)
    {
      // Just as an exammple, here I just show a MessageBox
      MessageBox.Show("You clicked on object " + i + "!!!");
    }
    

    【讨论】:

    • 感谢您的回复,我试过了,它可以工作,但我的问题仍然是我需要它是动态的,所以,我希望能够做你告诉我不用做的事情在 XAML 文件中声明列,有什么办法吗?
    • 您想在列中显示什么?我的意思是,它是否取决于某些参数?您可以轻松地手动和动态声明代码中的列,给我更多关于您需要什么的详细信息,我将向您展示一个您可以使用的好代码 sn-p
    • 谢谢。好吧,事实证明我的 dataGrid 将始终显示不同的数据集。这组数据可能包含按钮列、组合框列、复选框列或文本列。因此,我的想法是将 AutogenerateColumns 属性设置为 true 并将一个对象传递给它,该对象包含必须在某个时候显示的列结构和数据。出于这个原因,我不能手动定义 XAML 中的列。提前谢谢@Damascus
    【解决方案2】:

    绑定到自定义对象的 ObservableCollection 的简单示例。向自定义对象添加更多属性以匹配您希望行的外观。

     using System.Collections.ObjectModel;
    
     public MyClass
     {
          public ObservableCollection<MyObject> myList { get; set; }
    
          public MyClass()
          {
               this.DataContext = this;
               myList = new ObservableCollection<MyObject>();
               myList.Add(new MyObject() { MyProperty = "foo", MyBool = false };
               myList.Add(new MyObject() { MyProperty = "bar", MyBool = true };
          }
     }
    
     public MyObject
     {
          public string MyProperty { get; set; }
          // I believe will result in checkbox in the grid
          public bool MyBool { get; set; }
          //...as many properties as you want
     }
    

    使用 xaml

      <DataGrid ItemsSource= "{Binding myList}" />
    

    可能是一些小的语法错误,我完全是在 SO 窗口中写的。

    【讨论】:

    • 感谢您的回复,但我试图避免使用 DataTables,因为据我所知,DataColumn 不允许添加与文本不同的内容,例如组合框、按钮等控件,一个复选框,对吧?
    • 在这种情况下,您应该为您制作的自定义对象创建一个 ObservableCollection 来代表每一行,我将编辑一个基本实现。
    • 这行得通,但是,如果我想添加一个按钮或组合框,我应该声明我的属性的类型是什么?
    • 您可以放入一个项目模板选择器来检查属性的类型(或您可以设置的其他内容)并将其设置为按钮或组合框或网络浏览器或任何您想要的,我不有类型来编码一个例子,但谷歌 celltemplateselector for wpf datagrid
    【解决方案3】:

    我是 WPF 的新手,我使用 Damascus 的示例来学习将 List 绑定到数据网格。但是当我使用他的答案时,我发现我的数据网格会填充正确的行数,但不会填充 MyObject 类的任何属性。我做了更多的搜索,然后偶然发现了我必须做的事情。

    我必须封装 MyObject 类属性才能显示它们。将它们公开是不够的。

    之前:

    public class MyObject
    {
       public int MyID;
       public string MyString;
       public ICommand MyCommand;
    }
    

    之后:

    public class MyObject
    {
        private int _myID;
    
        public int MyID
        {
            get { return _myID; }
            set { _myID = value; }
        }
        private string _myString;
    
        public string MyString
        {
            get { return _myString; }
            set { _myString = value; }
        }
        private ICommand _myCommand;
    
        public ICommand MyCommand
        {
            get { return _myCommand; }
            set { _myCommand = value; }
        }
    }
    

    感谢 Damascus 提供了一个很好的例子,感谢 Dante 提出了一个很好的问题。我不知道这是否是由于您发布后版本发生了变化,但希望这会帮助像我这样的 WPF 新手。

    【讨论】:

      猜你喜欢
      • 2017-10-20
      • 2021-04-02
      • 1970-01-01
      • 2013-06-27
      • 1970-01-01
      • 2023-03-24
      • 2012-08-04
      • 2012-05-01
      • 2010-11-11
      相关资源
      最近更新 更多