C# 创建自定义 DataGrid 的 ItemsSource
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10760838/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Create a custom DataGrid's ItemsSource
提问by Dante
I am working with DataGrids but I am struggling to binding my data since the number of columns varies depending of the info that has to be showed.
我正在使用 DataGrids,但我正在努力绑定我的数据,因为列数因必须显示的信息而异。
So, what I have tried to do is to create and object which contains all the columns and rows that I need at some point and binding this object to the ItemsSourceproperty. Since I have worked with DataGridViews in WindowsForms I have in mind something like this:
所以,我试图做的是创建一个包含我在某个时候需要的所有列和行的对象,并将这个对象绑定到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);
But I haven't been able to find a way to do the same thing in WPF since I need some columns to be DataGridComboBoxColumns for example.
但是我一直无法在 WPF 中找到一种方法来做同样的事情,因为我需要一些列作为 DataGridComboBoxColumns 例如。
Actually I have read many post about it in this site, but none of them helped to me. I am really lost.
其实我在这个网站上读过很多关于它的帖子,但没有一个对我有帮助。我真的很失落。
Could anyone help me? I just need to be able to create a table which may contain DataGridTextColumns or `DataGridComboBoxColumns, etc, In order to bind this final object to the DataGrid's ItemsSource property.
有人可以帮助我吗?我只需要能够创建一个可能包含 DataGridTextColumns 或 `DataGridComboBoxColumns 等的表,以便将这个最终对象绑定到 DataGrid 的 ItemsSource 属性。
Hope someone can help me.
希望可以有人帮帮我。
采纳答案by Damascus
Okay, let me try to take an example which is similar to your needs
好的,让我尝试举一个与您的需求相似的示例
Let's assume we use this class:
假设我们使用这个类:
public class MyObject
{
public int MyID;
public string MyString;
public ICommand MyCommand;
}
And we are willing to display a DataGridlisting the ID, and having as a second column a Button, with the property MyStringas content, which, when clicked, launches the ICommandMyCommandwhich opens in a new window whatever you want.
并且我们愿意显示一个DataGridID 列表,并将 a 作为第二列Button,将属性MyString作为内容,单击它时,会启动ICommandMyCommand在新窗口中打开的任何您想要的内容。
Here is what you should have on the View side:
以下是您应该在 View 方面拥有的内容:
<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>
This will show a DataGridtaking all the content in an IEnumerable<MyObject>named 'MyList', and shows two columns as defined before.
这将显示一个名为“MyList”的DataGrid所有内容IEnumerable<MyObject>,并显示之前定义的两列。
Now if you need to define the command.
First, I recommend you read this introductory link to MVVMand take the RelayCommandclass (that's what we're gonna use for your problem)
现在,如果您需要定义命令。首先,我建议您阅读MVVM 的介绍性链接并参加RelayCommand课程(这就是我们将用于解决您的问题的内容)
So, in your ViewModel, the one which defines the MyList, here is how you should define some of the useful objects:
因此,在您的 中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 + "!!!");
}
回答by Kevin DiTraglia
A simple example of binding to a ObservableCollection of a custom object. Add more properties to the custom object to match what you want your rows to look like.
绑定到自定义对象的 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
}
with xaml
使用 xaml
<DataGrid ItemsSource= "{Binding myList}" />
Might be some small syntax errors, I wrote that entirely within the SO window.
可能是一些小的语法错误,我完全在 SO 窗口中写的。
回答by Kirk H
I am new to WPF and used Damascus's example to learn binding of a List to a datagrid. But when I used his answer I found that my datagrid would populate with the correct number of rows but not with any of the properties from the MyObject class. I did a bit more searching then stumbled across what I had to do by accident.
我是 WPF 的新手,并使用 Damascus 的示例来学习将列表绑定到数据网格。但是当我使用他的答案时,我发现我的数据网格会填充正确的行数,但不会填充 MyObject 类中的任何属性。我做了更多的搜索,然后偶然发现了我必须做的事情。
I had to encapsulate the MyObject class properties to have them show. It wasn't enough to have them be public.
我必须封装 MyObject 类属性才能显示它们。让他们公开是不够的。
Before:
前:
public class MyObject
{
public int MyID;
public string MyString;
public ICommand MyCommand;
}
After:
后:
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; }
}
}
Thank you Damascus for a great example and thank you Dante for a great question. I don't know if this is due to a change in version since your post but hopefully this will help others new to WPF like me.
感谢大马士革提供了一个很好的例子,也感谢但丁提出了一个很好的问题。我不知道这是否是由于自您的帖子以来版本发生了变化,但希望这会帮助像我这样的 WPF 新手。

