好的,让我尝试举一个与您的需求相似的示例
假设我们使用这个类:
public class MyObject
{
public int MyID;
public string MyString;
public ICommand MyCommand;
}
我们愿意显示DataGrid
ID 列表,并将 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 + "!!!");
}
这应该足以创建您想要的任何内容。如您所见,每个Button
人都会调用一个方法(ShowWindow
),该方法被定义为显示您的新窗口,在里面做任何您需要的事情。RelayCommand
顾名思义,它实际上只是在这里将按钮触发的命令传递给包含执行逻辑的方法。
而且......我认为这就是你所需要的。抱歉,BTW 回复晚了
编辑 - 手动/动态生成列
以下代码是我遇到类似问题时必须执行的代码的一部分。我的问题是,每次 a 发生变化时,我都需要更改显示的ComboBox
列SelectedItem
。所以我把它放在一个SelectionChanged
事件处理程序中。我不知道你究竟需要在哪里生成你的列,但我会给你一个一般的例子。
假设你ItemsSource
是一个ObservableCollection<MyNewObject>
MyNewObject
如下:
public class MyNewObject
{
public IList<string> MyStrings { get; set; }
}
您应该在代码中的某个位置(应该是当您需要生成列时)以下代码,该代码生成的列数等于MyNewObject
列表中第一个列的长度(注意:这是在代码隐藏中,并且DataGrid
您正在处理的名为 dataGrid )
ObservableCollection<MyNewObject> source = dataGrid.ItemsSource as ObservableCollection<MyNewObject>;
if (source == null || source.Count == 0)
{
return;
}
MyNewObject firstObject = source[0];
for(int i = 0; i < firstObject.MyStrings.Count; i++)
{
// Creates one column filled with buttons for each string
DataGridTemplateColumn columnToAdd = new DataGridTemplateColumn();
columnToAdd.Width = 110; // I set a manual width, but you can do whatever you want
columnToAdd.Header = "Header number " + i;
// Create the template with a Button inside, bound to the appropriate string
DataTemplate dataTemplate = new DataTemplate(typeof(Button));
FrameworkElementFactory buttonElement = new FrameworkElementFactory(typeof(Button));
Binding binding = new Binding("MyStrings[" + i + "]");
binding.Mode = BindingMode.TwoWay;
binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
buttonElement.SetBinding(Button.ContentProperty, binding);
// Do the same here for your command, or for whatever you want to do when the user clicks on this button
dataTemplate.VisualTree = buttonElement;
columnToAdd.CellTemplate = dataTemplate;
dataGrid.Columns.Add(columnToAdd);
}
这将为在第一个对象中找到的每个字符串创建一列。然后,使用您需要的任何命令或显示技巧来增强它!