Vahid
Vahid

Reputation: 5454

Bind a DataGrid to an ObservableCollection<T> in WPF

How can I bind a Datagrid with two columns (DataGridTextColumn and DataGridComboBoxColumn) to an ObservableCollection<Team> Teams?

The DataGridTextColumn is bound correctly. But nothing is displayed in DataGridComboBoxColumn.

Code-behind

   public class Team
   {
      public string Name { get; set; }
      public List<string> Members { get; set; }
   }

   public class ViewModel : INotifyPropertyChanged
   {
      public event PropertyChangedEventHandler PropertyChanged;

      private ObservableCollection<Team> teams = new ObservableCollection<Team>
      {
         new Team()
         {
            Name = "A", Members = new List<string> {"John", "Jack"},
         },
         new Team()
         {
            Name = "B", Members = new List<string> {"Sarah", "Anna"},
         }
      };
      public ObservableCollection<Team> Teams
      {
         get { return teams; }
         set
         {
            teams = value;
            RaisePropertyChanged("Teams");
         }
      }

      private void RaisePropertyChanged(string propertyName)
      {
         var handler = PropertyChanged;
         if (handler == null) return;

         handler(this, new PropertyChangedEventArgs(propertyName));
      }
   }

XAML

<DataGrid ItemsSource="{Binding Path=Teams}"
          AutoGenerateColumns="False">
    <DataGrid.Columns>

        <DataGridTextColumn Header="Team" 
                                    IsReadOnly="True"
                                    Width="*"
                                    Binding="{Binding Name}"/>

        <DataGridComboBoxColumn Header="Members" 
                                        Width="*"
                                        />

    </DataGrid.Columns>
</DataGrid>

Upvotes: 0

Views: 3849

Answers (2)

tym32167
tym32167

Reputation: 4891

Your need to setup DataContext property of your control with instance of ViewModel. Like, in control constructor

this.DataContext = new ViewModel();

and fill DisplayMemberPath in your XAML

<DataGridTextColumn Header="Team" DisplayMemberPath="Name" ...

UPDATE

I was inccorrect. Because DataGridComboboxColumn does not inherit DataContext, to do what you want you have to do in following way:

    <DataGrid ItemsSource="{Binding Path=Teams}"
      AutoGenerateColumns="False">
        <DataGrid.Columns>

            <DataGridTextColumn Header="Team" 
                                IsReadOnly="True"
                                Width="*"
                                 Binding="{Binding Name}" />

            <DataGridComboBoxColumn Header="Members" 
                                    Width="*"
                                    >

                <DataGridComboBoxColumn.ElementStyle>
                    <Style TargetType="ComboBox">
                        <Setter Property="ItemsSource" Value="{Binding Path=Members}" />
                    </Style>
                </DataGridComboBoxColumn.ElementStyle>

                <DataGridComboBoxColumn.EditingElementStyle>
                    <Style TargetType="ComboBox">
                        <Setter Property="ItemsSource" Value="{Binding Path=Members}" />
                    </Style>
                </DataGridComboBoxColumn.EditingElementStyle>
            </DataGridComboBoxColumn>

        </DataGrid.Columns>
    </DataGrid>

Upvotes: 1

Rom
Rom

Reputation: 1193

Just use "DataGridTemplateColumn". Dont forget to add a selectedItem Member.

            <DataGridTemplateColumn Header="Members">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate DataType="wpfApplication1:Team">
                        <ComboBox ItemsSource="{Binding Members}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>

Upvotes: 1

Related Questions