Search code examples
c#wpfxamlmvvmcompositecollection

XAML binding to CompositeCollection


I have only one datagrid in a single view but the collections which are ItemsSource's of this datagrid are in different View Models. So is it possible to bind this single datagrid in view with the collections in two different View Models?

For each row in the grid, display an item from one collection, and an item from the other collection..! to display all columns in one row.

xaml:

DataContext="{DynamicResource ViewModelCombine}"> 

<Window.Resources> 
    <vm:ViewModelCombine x:Key="ViewModelCombine"/> 
</Window.Resources> 

<Grid> 
        <Grid.RowDefinitions> 
            <RowDefinition Height="Auto"/> 
        </Grid.RowDefinitions> 

     <DataGrid> 

            <DataGrid.Resources>
                <CollectionViewSource x:Key="ViewModelPulse" Source="{Binding VP}"/>
                <CollectionViewSource x:Key="ViewModeltherapy" Source="{Binding VT}"/>
            </DataGrid.Resources>

            <DataGrid.ItemsSource> 
                <CompositeCollection> 
                    <CollectionContainer Collection="{Binding Source={StaticResource ViewModelCombine}, Path=VP}" /> 
                    <CollectionContainer Collection="{Binding Source={StaticResource ViewModelCombine}, Path=VT}" /> 
                </CompositeCollection> 
            </DataGrid.ItemsSource> 

            <DataGrid.Columns> 
                <DataGridTextColumn Header="AMP" Binding="{Binding AMP}" Width="100"/> 
                <DataGridTextColumn Header="PW" Binding="{Binding PW}" Width="100" /> 
                <DataGridTextColumn Header="DZ0" Binding="{Binding DZ0}" Width="100" /> 
                <DataGridTextColumn Header="DELTA" Binding="{Binding DELTA}" Width="100" /> 
                <DataGridTextColumn Header="DZ1" Binding="{Binding DZ1}"   Width="100"/> 
                <DataGridTextColumn Header="M" Binding="{Binding M}" Width="100" /> 
                <DataGridTextColumn Header="DZ2" Binding="{Binding DZ2}" Width="100" /> 
                <DataGridTextColumn Header="N" Binding="{Binding N}" Width="100" /> 
            </DataGrid.Columns> 

    </DataGrid> 

</Grid> 

xaml.cs:

public MainWindow() 
{ 
    InitializeComponent(); 
    ViewModelCombine VMC = new ViewModelCombine(); 
    this.DataContext = VMC; 
} 

ViewModelCombine.cs

public class ViewModelCombine 
{ 
    public ViewModelTherapy VT { get; set; } 
    public ViewModelPulse VP { get; set; }

    public ViewModelCombine() 
    { 
        VT = new ViewModelTherapy(); 
        VP = new ViewModelPulse(); 
    } 

} 

As per the above code, it displays like this Output..but, wanted to display all columns in one row.

So is it possible to bind this single datagrid in view with the collections in two different View Models?

Thanks for your help.


Solution

  • And here is a working example of your code. I replaced the Itemsource of the Datagrid and made ViewModelTherapy and ViewModelPulse to Observable collections.

    Code:

     public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
    
    
            ViewModelCombine VMC = new ViewModelCombine();
            VMC.VP.Add(new ViewModelPulse() { ID = 1, Name = "test1", xaxa = "xaxa" });
            VMC.VT.Add(new ViewModelTherapy() { ID = 2 Name = "test2", Description = "desc" });
            this.DataContext = VMC;
        }
    
    }
    
    public class ViewModelCombine
    {
        public ObservableCollection<ViewModelTherapy> VT { get; set; }
        public ObservableCollection<ViewModelPulse>  VP { get; set; }
    
        public ViewModelCombine()
        {
            VT = new ObservableCollection<ViewModelTherapy>();
            VP = new ObservableCollection<ViewModelPulse>();
        }
    
    }
    
    public class ViewModelTherapy
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
    
    }
    
    public class ViewModelPulse
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public string xaxa { get; set; }
    
    }
    

    Xaml:

    <Window.Resources>
        <CollectionViewSource x:Key="ViewSource1" Source="{Binding VT}"/>
        <CollectionViewSource x:Key="ViewSource2" Source="{Binding VP}"/>
    
        <CompositeCollection x:Key="CombinedCollection">
            <CollectionContainer Collection="{Binding Source={StaticResource ViewSource1}}" />
            <CollectionContainer Collection="{Binding Source={StaticResource ViewSource2}}" />
         </CompositeCollection>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
    
        <DataGrid ItemsSource="{StaticResource CombinedCollection}">
    
    
            <DataGrid.Columns>
                <DataGridTextColumn Header="AMP" Binding="{Binding ID}" Width="100"/>
                <DataGridTextColumn Header="PW" Binding="{Binding Name}" Width="100" />
                <DataGridTextColumn Header="DZ0" Binding="{Binding xaxa}" Width="100" />
                <DataGridTextColumn Header="DELTA" Binding="{Binding Description}" Width="100" />
            </DataGrid.Columns>
    
        </DataGrid>
    
    </Grid>
    

    And here is a screenshot of the result

    enter image description here