0

我有一个可以添加和删除记录的 DataGrid (dataGrid1)。

基于该 dataGrid1,我想根据 ID 和类型创建一个带有按钮的新网格。Cols 还必须动态提供 add 的 DataSource,但这只是在 Window_Loaded 本身中第一次生成时。可以根据 dataGrid1 中的更改添加/删除行。我想要这样的东西:

在此处输入图像描述

每次单击 Btn 时,都会打开一个新窗口,用于输入特定类型和特定 ID。如果已输入详细信息,则 btn 的文本将为“更新”,否则为“添加”。

执行此操作的最佳资源/控制可能是什么?目前,我刚刚做了一个 Grid 有 2 个稳定的 cols。以上使用 Grid、DataGrid 或其他东西的任何想法。添加/删除行将以何种方式和方式很容易。

任何帮助表示赞赏。

4

1 回答 1

1

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

假设我们使用这个类:

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 + "!!!");
}

这应该足以创建您想要的任何内容。如您所见,每个Button人都会调用一个方法(ShowWindow),该方法被定义为显示您的新窗口,在里面做任何您需要的事情。RelayCommand顾名思义,它实际上只是在这里将按钮触发的命令传递给包含执行逻辑的方法。

而且......我认为这就是你所需要的。抱歉,BTW 回复晚了

编辑 - 手动/动态生成列

以下代码是我遇到类似问题时必须执行的代码的一部分。我的问题是,每次 a 发生变化时,我都需要更改显示的ComboBoxSelectedItem。所以我把它放在一个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);
}

这将为在第一个对象中找到的每个字符串创建一列。然后,使用您需要的任何命令或显示技巧来增强它!

于 2012-05-23T18:47:51.647 回答