2

我正在使用 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 属性。

希望可以有人帮帮我。

4

3 回答 3

6

好的,让我尝试举一个与您的需求相似的示例

假设我们使用这个类:

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

我们愿意显示DataGridID 列表,并将 a 作为第二列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获取IEnumerable<MyObject>名为“MyList”中的所有内容,并显示之前定义的两列。

现在,如果您需要定义命令。首先,我建议您阅读此 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 + "!!!");
}
于 2012-05-25T20:59:41.703 回答
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
 }

与 xml

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

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

于 2012-05-25T20:21:11.917 回答
0

我是 WPF 的新手,并使用大马士革的示例来学习将列表绑定到数据网格。但是当我使用他的答案时,我发现我的数据网格会填充正确的行数,但不会填充 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; }
    }
}

感谢大马士革提供了一个很好的例子,感谢但丁提出了一个很好的问题。我不知道这是否是由于自您的帖子以来版本发生了变化,但希望这将有助于像我这样的 WPF 新手。

于 2013-12-17T14:26:23.653 回答