Create a custom DataGrid's ItemsSource

后端 未结 3 922
不思量自难忘°
不思量自难忘° 2020-12-21 18:05

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.

So, what I have t

相关标签:
3条回答
  • 2020-12-21 18:18

    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 DataGrid listing the ID, and having as a second column a Button, with the property MyString as content, which, when clicked, launches the ICommand MyCommand which opens in a new window whatever you want.

    Here is what you should have on the View side:

        <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 DataGrid taking all the content in an IEnumerable<MyObject> named 'MyList', and shows two columns as defined before.

    Now if you need to define the command. First, I recommend you read this introductory link to MVVM and take the RelayCommand class (that's what we're gonna use for your problem)

    So, in your ViewModel, the one which defines the MyList, here is how you should define some of the useful objects:

    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 + "!!!");
    }
    
    0 讨论(0)
  • 2020-12-21 18:19

    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.

     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

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

    Might be some small syntax errors, I wrote that entirely within the SO window.

    0 讨论(0)
  • 2020-12-21 18:29

    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.

    I had to encapsulate the MyObject class properties to have them show. It wasn't enough to have them be public.

    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.

    0 讨论(0)
提交回复
热议问题