Home > Software engineering >  MVVM Binding DataGrid to one Object in List<Object>
MVVM Binding DataGrid to one Object in List<Object>

Time:07-14

I have a ObservableCollection<object>. Each object has a list of properties that are displayed in the datagrid. One object should be displayed in the datagrid at a time. The user then modifies property values within the datagrid. The user should be able to choose which object is displayed in the datagrid using a combobox.

I don't know how to have the DataGrid have a binding with the original ObservableCollection<object>. My current solution is to have a standalone object with a binding to the ComboBox's SelectedItem, and the DataGrid is bound to that object.

<ComboBox x:Name="ifcCombo" 
            DisplayMemberPath="ifcEntity"
            SelectedItem="{Binding chosenConcept}"
            ItemsSource="{Binding ConceptList}"/>

<DataGrid x:Name="propertiesTable"
          ItemsSource="{Binding chosenConcept.propertyList}">
     <DataGrid.Columns>
          <DataGridTextColumn Binding="{Binding PropertyName}"/>
          <DataGridTextColumn Binding="{Binding Mapping}"/>
     </DataGrid.Columns>
</DataGrid>

This can't be the best way to do this. Although I do have a working binding on my DataGrid. Now, in my ViewModel, I have an object that needs to manually replace an object that is in the original ObservableCollection<object>. So I can do a Linq query, and replace that object, but I feel there must be a more proper way to do this binding.

private ObservableCollection<EntityConcept> _ConceptList = new ObservableCollection<EntityConcept>();
private EntityConcept _chosenConcept = new EntityConcept(); 

To provide some more context. I will show the object(class) for EntityConcept that I am talking about:

public class EntityConcept
    {
        private ObservableCollection<PropertyItem> _propertyList;
        private string _ifcEntity;

        public ObservableCollection<PropertyItem> propertyList
        {
            get
            {
                return _propertyList;
            }
            set
            {
                _propertyList = value;
            }
        }             
        public string ifcEntity
        {
            get
            {
                return _ifcEntity;
            }
            set
            {
                _ifcEntity = value;
            }
        }
    }

The PropertyItem class is an object with many properties, but they are all primitives.

Also, you get bonus points if your solution will work with a ListCollectionView, because I eventually want to display this information in groups.

CodePudding user response:

You don't need to have a standalone object with a binding to the ComboBox's SelectedItem. Bind to the selected property directly in the XAML:

<ComboBox x:Name="ifcCombo" 
            DisplayMemberPath="ifcEntity"
            ItemsSource="{Binding ConceptList}"/>

<DataGrid x:Name="propertiesTable" AutoGenerateColumns="False"
          DataContext="{Binding ElementName=ifcCombo, Path=SelectedItem}"
          ItemsSource="{Binding propertyList}">
     <DataGrid.Columns>
          <DataGridTextColumn Binding="{Binding PropertyName}"/>
          <DataGridTextColumn Binding="{Binding Mapping}"/>
     </DataGrid.Columns>
</DataGrid>

Also add AutoGenerateColumns="False" in order to prevent generating the columns twice.

CodePudding user response:

assuming you also want to do something with the chosen Concept

<ComboBox x:Name="ifcCombo" 
          DisplayMemberPath="ifcEntity"
          ItemsSource="{Binding ConceptList}"
          SelectedItem="{Binding ChosenConcept}"/>
<Grid>
    <Grid.Resources>
        <CollectionViewSource x:Key="propertyListCollection" Source="{Binding ChosenConcept.propertyList}">
            <CollectionViewSource.GroupDescriptions>
                <PropertyGroupDescription PropertyName="Foo"/>
            </CollectionViewSource.GroupDescriptions>
        </CollectionViewSource>
    </Grid.Resources>
    <DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Source={StaticResource propertyListCollection}}">
        <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding PropertyName}"/>
            <DataGridTextColumn Binding="{Binding Mapping}"/>
        </DataGrid.Columns>
    </DataGrid>
</Grid>
  • Related