Merging two ObservableCollection and Bind Datagrid with this MergedCollection as source using CompositeCollection

你说的曾经没有我的故事 提交于 2019-12-12 03:05:58

问题


.Xaml

DataContext="{DynamicResource ViewModelCombine}">

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

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

    <DataGrid x:Name="grd">

            <DataGrid.ItemsSource>
            <CompositeCollection>
                <CollectionContainer Collection="{Binding  Source={StaticResource ViewModelCombine}, Path=MergedSource}"/>
            </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_View}" 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 partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        ViewModelCombine VMC = new ViewModelCombine();
        grd.DataContext = VMC;
    }
}

ViewModelCombine.cs

public class ViewModelCombine
{
    private ObservableCollection<TherapyTiming> secondsource;
    public ObservableCollection<TherapyTiming> SecondSource
    {
        get { return secondsource; }
        set { secondsource = value; }
    }

    private ObservableCollection<PulseTiming> firstsource;
    public ObservableCollection<PulseTiming> FirstSource
    {
        get { return firstsource; }
        set { firstsource = value; }
    }

    private CompositeCollection mergedSource;
    public CompositeCollection MergedSource
    {
        get { return mergedSource; }
        set { mergedSource = value; OnPropertyChanged("MergedSource"); }
    }

    public ViewModelCombine()
    {
        var secondinfo = new ViewModelTherapy();
        SecondSource = secondinfo;

        var firstinfo = new ViewModelPulse();
        FirstSource = firstinfo;

        mergedSource = new CompositeCollection();
        CollectionContainer collection1 = new CollectionContainer() { Collection = SecondSource };
        CollectionContainer collection2 = new CollectionContainer() { Collection = FirstSource };

        mergedSource.Add(collection1);
        mergedSource.Add(collection2);
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }
}

Issue while binding Datagrid to MergedCollection as itemsource using CompositeCollection..displays the data in two rows instead of one row and check output here.

Requirement is to display all columns in one row...! Thanks.


回答1:


Ok. The problem is in the code below

 mergedSource.Add(collection1);
    mergedSource.Add(collection2);

This code creates one list with unique items of both collections without merging their properties. So that's why you have the output as on your link.

Instead of doing that i would suggest the following solution

  1. Create a collection of ObservableCollection<Newobject>
  2. Newobject should contain all the properties from PulseTiming and TherapyTiming
  3. Insted of adding the items from collection1 and collection2 on the same list, i would merge (copy all properties) each item from collection1 and collection2 based on their ids(add them if you don't have id properties cause it will help you identify the connection between the colelctions) to the Newobject.

  4. Make sure that you bind your datagrid to the new collection(itemsource)

That approach will show your items in one row per item. But you cannot do that without merging the properties into a new object.

UPDATED: Working sample

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 = 1, Name = "test1", Description = "desc" });
        VMC.VP.Add(new ViewModelPulse() { ID = 2, Name = "test2", xaxa = "xaxa2" });
        VMC.VT.Add(new ViewModelTherapy() { ID =2, Name = "test2", Description = "desc2" });
        VMC.BuildSource();
        this.DataContext = VMC;
    }

}

public class ViewModelCombine
{
    public ObservableCollection<ViewCommon> Source { get; set; }

    public void BuildSource()
    {
        Source.Clear();
        foreach(var itm in VT)
        {
            var itmF = VP.FirstOrDefault(x => x.ID == itm.ID);
            if(itmF != null)
            {
                Source.Add(new ViewCommon() {
                    ID = itm.ID,
                    Description = itm.Description,
                    Name = itm.Name,
                    xaxa = itmF.xaxa
                });
            }
        }
    }

    public ObservableCollection<ViewModelTherapy> VT { get; set; }
    public ObservableCollection<ViewModelPulse>  VP { get; set; }

    public ViewModelCombine()
    {
        Source = new ObservableCollection<ViewCommon>();
        VT = new ObservableCollection<ViewModelTherapy>();
        VP = new ObservableCollection<ViewModelPulse>();
    }

}

public class ViewCommon
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public string xaxa { get; set; }


}
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 Source}"/>

    <CompositeCollection x:Key="CombinedCollection">
        <CollectionContainer Collection="{Binding Source={StaticResource ViewSource1}}" />
     </CompositeCollection>
</Window.Resources>
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>

    <DataGrid ItemsSource="{StaticResource CombinedCollection}">


        <DataGrid.Columns>
            <DataGridTextColumn Header="ID" Binding="{Binding ID}" Width="100"/>
            <DataGridTextColumn Header="Name" Binding="{Binding Name}" Width="100" />
            <DataGridTextColumn Header="xaxa" Binding="{Binding xaxa}" Width="100" />
            <DataGridTextColumn Header="Description" Binding="{Binding Description}" Width="100" />
        </DataGrid.Columns>

    </DataGrid>

</Grid>

Screenshot:



来源:https://stackoverflow.com/questions/40147381/merging-two-observablecollection-and-bind-datagrid-with-this-mergedcollection-as

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!