Объединение двух наблюдаемых коллекций и привязка сетки данных к этой объединенной коллекции в качестве источника с использованием CompositeCollection

#wpf #xaml #mvvm #data-binding #compositecollection

#wpf #xaml #mvvm #привязка данных #compositecollection

Вопрос:

.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));
        }
    }
}
  

Проблема при привязке Datagrid к объединенной коллекции в качестве источника элементов с использованием CompositeCollection .. отображает данные в двух строках вместо одной строки и проверяет вывод здесь.

Требуется отобразить все столбцы в одной строке …! Спасибо.

Ответ №1:

ОК. Проблема заключается в приведенном ниже коде

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

Этот код создает один список с уникальными элементами обеих коллекций без объединения их свойств. Вот почему у вас есть выходные данные, указанные в вашей ссылке.

Вместо этого я бы предложил следующее решение

  1. Создайте коллекцию ObservableCollection<Newobject>
  2. Newobject должен содержать все свойства из PulseTiming и TherapyTiming
  3. Вместо добавления элементов из коллекции1 и коллекции2 в один список я бы объединил (скопировал все свойства) каждый элемент из коллекции1 и коллекции2 на основе их идентификаторов (добавьте их, если у вас нет свойств идентификатора, потому что это поможет вам определить связь между коллекциями) с Newobject.

  4. Убедитесь, что вы привязали свою сетку данных к новой коллекции (itemsource)

Такой подход будет отображать ваши элементы в одной строке для каждого элемента. Но вы не можете сделать это без объединения свойств в новый объект.

ОБНОВЛЕНО: Рабочий образец

Код:

     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>
  

Скриншот:

введите описание изображения здесь

Комментарии:

1. Хорошо. Я был бы признателен, если бы вы могли предоставить образец, как вы предложили ..!

2. Я имею в виду пример кода для объединения свойств из двух коллекций ..!

3. Я почти близок к требованию, но немного запутался.. Могу ли я получить ваш почтовый идентификатор, чтобы переслать образец моего проекта ..!

4. Ну, я не могу опубликовать свою информацию здесь (это противоречит правилам сайта). Но я полагаю, что я ответил на ваш вопрос. Вы можете задать здесь снова, если у вас есть еще какие-либо вопросы, и я постараюсь ответить как можно скорее.

5. Объединенная коллекция будет иметь «ключ», который будет определять строку. Затем два элемента, которые составляют «строку», будут объединены в один объект, который содержит свойства обоих элементов.