Привязка TreeView к коллекции с разными типами объектов на одном уровне - PullRequest
1 голос
/ 27 февраля 2020

Я хочу связать свой элемент управления Treeview с коллекцией, которая содержит объекты типа MeasurementResult. Сам объект MeasurementResult имеет две коллекции: одну для MeasurementInfo и одну для типов DeviceInfo.

После поиска в Google и поиска в SO я обнаружил, что лучшим решением может быть CompositeCollection. Проблема, с которой я столкнулся, заключается в том, что я просто не могу понять, как определить (иерархический?!) DataTemplate так, чтобы мои данные отображались в древовидной структуре так, как я хочу.

В конечном итоге Я хотел бы иметь такую ​​структуру TreeView:

-MeasurementResult1
---MeasurementInformation
------MeasurementInformation1
------MeasurementInformation2
------MeasurementInformation3
---DeviceInformation
------DeviceInformation1
------DeviceInformation2
------DeviceInformation3
-MeasurementResult2
---MeasurementInformation
------MeasurementInformation1
------MeasurementInformation2
------MeasurementInformation3
---DeviceInformation
------DeviceInformation1
------DeviceInformation2
------DeviceInformation3
-MeasurementResultN

Но проблема в том, что мой текущий TreeView выглядит так:

TreeView

Вложенные свойства для MeasurementData и DeviceData не отображаются в моем TreeView.

Код, который у меня есть, XAML:

<local:TreeViewSampleData x:Key="TreeViewSampleData"/>

<DataTemplate x:Key="MeasurementDataTemplate">
    <StackPanel Orientation="Vertical">
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="Finished: " Margin="0,0,10,0"/>
            <TextBlock Text="{Binding Finished}" />
        </StackPanel>
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="Median: " Margin="0,0,10,0"/>
            <TextBlock Text="{Binding Median}" />
        </StackPanel>
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="Maximum: " Margin="0,0,10,0"/>
            <TextBlock Text="{Binding Maximum}" />
        </StackPanel>
    </StackPanel>
</DataTemplate>

<HierarchicalDataTemplate x:Key="DeviceDataTemplate" DataType="{x:Type local:DeviceData}" ItemTemplate="{StaticResource MeasurementDataTemplate}" 
       ItemsSource="{Binding MeasurementData}">
    <TextBlock Text="{Binding Name}" />
</HierarchicalDataTemplate>

<HierarchicalDataTemplate x:Key="MeasurementResultTemplate" DataType="{x:Type local:MeasurementResult}" ItemTemplate="{StaticResource DeviceDataTemplate}" 
       ItemsSource="{Binding Measurements}">
    <TextBlock Text="{Binding Name}" />
</HierarchicalDataTemplate>


    <telerik:RadTreeView x:Name="tvMeasResults" 
                            ItemsSource="{Binding Source={StaticResource TreeViewSampleData}, Path = MeasurementResults}" 
                            ItemTemplate="{StaticResource MeasurementResultTemplate}"
                         >
    </telerik:RadTreeView>

Мои родственные классы:

public class MeasurementResult
{
    public string Name { get; set; } = "Measurement Result";
    internal ObservableCollection<MeasurementInfo> MeasurementInfo { get; set; }
    internal ObservableCollection<DeviceInfo> DeviceInfo { get; set; }

    public CompositeCollection Measurements
    {
        get
        {
            var items = new CompositeCollection();
            items.Add(new CollectionContainer { Collection = MeasurementInfo });
            items.Add(new CollectionContainer { Collection = DeviceInfo });
            return items;
        }
    }

    public MeasurementResult()
    {
        MeasurementInfo = new ObservableCollection<MeasurementInfo>();
        DeviceInfo = new ObservableCollection<DeviceInfo>();
    }
}

public class MeasurementInfo
{
    public string Name { get; set; } = "Measurement Information";
    public ObservableCollection<MeasurementData> ThicknessData { get; set; }

    public MeasurementInfo()
    {
        ThicknessData = new ObservableCollection<MeasurementData>();
    }
}

public class MeasurementData
{
    public DateTime Finished { internal set; get; }
    public double Median { internal set; get; }
    public double Maximum { internal set; get; }

    public MeasurementData()
    {
        Finished = DateTime.Now;
        Median = 150;
        Maximum = 200;
    }
}

public class DeviceInfo
{
    public string Name { get; set; } = "Device Information";
    public ObservableCollection<DeviceData> DeviceData { get; set; }

    public DeviceInfo()
    {
        DeviceData = new ObservableCollection<DeviceData>();
    }
}

public class DeviceData
{
    public DateTime Finished { internal set; get; }
    public int Port { internal set; get; }
    public int Slot { internal set; get; }

    public DeviceData()
    {
        Finished = DateTime.Now;
        Port = 1;
        Slot = 1;
    }
}

Что не так с моими привязками? Я думаю, что DataTemplates не так, но я не мог понять, как определить их, чтобы получить ожидаемый результат.

1 Ответ

2 голосов
/ 27 февраля 2020

Это позволит вам добавить указанные c элементы к указанным c листам, и они будут объединены GetEnumerator, поэтому TreeView представляет вещи так, как вы ожидали.

using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace WpfApp1
{
    public partial class MainWindow
    {
        public MainWindow()
        {
            InitializeComponent();

            var item = new InformationTreeItem("ROOT")
            {
                Children =
                {
                    new InformationTreeItem("Level 1")
                    {
                        DeviceInformation =
                        {
                            new DeviceInformation("Device 1/1"),
                            new DeviceInformation("Device 1/2")
                        },
                        MeasurementInformation =
                        {
                            new MeasurementInformation("Measure 1/1"),
                            new MeasurementInformation("Measure 1/2")
                        },
                        Children =
                        {
                            new InformationTreeItem("Level 2")
                            {
                                DeviceInformation =
                                {
                                    new DeviceInformation("Device 2/1"),
                                    new DeviceInformation("Device 2/2")
                                },
                                MeasurementInformation =
                                {
                                    new MeasurementInformation("Measure 2/1"),
                                    new MeasurementInformation("Measure 2/2")
                                },
                                Children =
                                {
                                    new InformationTreeItem("Level 3")
                                }
                            }
                        }
                    }
                }
            };

            DataContext = item;
        }
    }

    public interface IInformation
    {
        string Description { get; }
    }

    public class InformationTreeItem : IEnumerable<IInformation>, IInformation
    {
        public InformationTreeItem(string description)
        {
            Description = description;
        }

        private InformationTreeItem(string description, IList<IInformation> children)
        {
            Description = description;
            Children = children;
        }

        public IList<IInformation> Children { get; } = new List<IInformation>();

        public IList<DeviceInformation> DeviceInformation { get; } = new List<DeviceInformation>();

        public IList<MeasurementInformation> MeasurementInformation { get; } = new List<MeasurementInformation>();

        public string Description { get; }

        public IEnumerator<IInformation> GetEnumerator()
        {
            var list = new List<IInformation>();

            if (DeviceInformation.Any())
            {
                list.Add(new InformationTreeItem(nameof(DeviceInformation), new List<IInformation>(DeviceInformation)));
            }

            if (MeasurementInformation.Any())
            {
                list.Add(new InformationTreeItem(nameof(MeasurementInformation), new List<IInformation>(MeasurementInformation)));
            }

            foreach (var child in Children)
            {
                list.Add(child);
            }

            return list.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        public override string ToString()
        {
            return Description;
        }
    }

    public class DeviceInformation : IInformation
    {
        public DeviceInformation(string description)
        {
            Description = description;
        }

        public string Description { get; }

        public override string ToString()
        {
            return Description;
        }
    }

    public class MeasurementInformation : IInformation
    {
        public MeasurementInformation(string description)
        {
            Description = description;
        }

        public string Description { get; }

        public override string ToString()
        {
            return Description;
        }
    }
}

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...