Как правильно связать объект (ы) с деревом - PullRequest
0 голосов
/ 11 февраля 2020

Я учил себя C# и хотел написать приложение WPF, которое будет использовать древовидную структуру. Хотя у меня чертовски много времени выясняется, как заставить привязку данных работать с ним.

Может кто-нибудь сказать мне, где я здесь не так? На данный момент я просто пытаюсь получить что-то, что-либо, чтобы отобразить в дереве. Ресурсы, которые я нашел, которые показывают, как использовать древовидную структуру, были довольно запутанными для меня.

Заранее спасибо за ваше время

Редактировать: Спасибо за ответы. Добавление ItemSource = {Cars} в древовидную структуру привело к созданию двух машин, которые я создал. Как мне go сделать автомобиль расширяемым для отображения списка функций? Я постараюсь выяснить это самостоятельно, но любая помощь приветствуется, потому что мне удалось немного разочароваться в этом.

Cars.cs

using System;
using System.Collections.Generic;

namespace TreeViewTest
{
    public class Cars
    {
        public List<Car> CarCollection { get; set; }

    }

    public class Car
    {
        public String Make { get; set; }
        public String Model { get; set; }
        public int Year { get; set; }
        public List<String> Features { get; set; }

    }
}

MainWindowViewModel.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace TreeViewTest
{
    public class MainWindowViewModel : INotifyPropertyChanged
    {
        private List<Car> _Cars;

        public List<Car> Cars
        {
            get { return _Cars; }
            set
            {

                if (_Cars == value)
                {
                    return;
                }   
                _Cars = value;
                NotifyPropertyChanged();
            }
        }

        public Car _Car;
        public Car Car
        {
            get { return _Car; }
            set
            {
                if (_Car == value)
                {
                    return;
                }
                _Car = value;
                NotifyPropertyChanged();

            }
        }


        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.Windows;

namespace TreeViewTest
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        MainWindowViewModel _MainWindowContext = new MainWindowViewModel();

        public MainWindow()
        {


            DataContext = _MainWindowContext;
            List<String> basicFeatures = new List<string>() { "Air Conditioning", "AM/FM Radio"};
            Car Rav4 = new Car() { Make = "Toyota", Model = "Rav4", Year = 2001, Features = basicFeatures};
            Car ModelX = new Car() { Make = "Tesla", Model = "Model X", Year = 2020, Features = basicFeatures};
            List<Car> theseCars = new List<Car>() { Rav4, ModelX };
            _MainWindowContext.Car = Rav4;
            _MainWindowContext.Cars = theseCars;

            InitializeComponent();
        }


    }
}

MainWindow.xaml

<Window x:Class="TreeViewTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TreeViewTest"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <StackPanel Grid.Row="0" Grid.Column="0">    
            <TreeView Grid.Row="0" Grid.Column="0" Height="150">
                <TreeView.ItemTemplate>
                    <HierarchicalDataTemplate ItemsSource="{Binding CarCollection}" DataType="{x:Type local:Cars}">
                        <StackPanel Orientation="Horizontal">
                            <TreeViewItem Header="{Binding Make}"/>
                        </StackPanel>
                    </HierarchicalDataTemplate>
                </TreeView.ItemTemplate>
            </TreeView>

        </StackPanel>

    </Grid>
</Window>

1 Ответ

0 голосов
/ 11 февраля 2020

Добавьте

ItemsSource="{Binding Cars}"

в TreeView

РЕДАКТИРОВАТЬ

Таким образом, вы бы расположили автомобили с соответствующими функциями в качестве дочерних узлов.

<TreeView Grid.Row="0" Grid.Column="0" Height="150" ItemsSource="{Binding Cars}">
    <TreeView.Resources>
        <HierarchicalDataTemplate DataType="{x:Type local:Car}" ItemsSource="{Binding Features}">
            <TextBlock Text="{Binding Make}"/>
            <HierarchicalDataTemplate.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding}"/>
                </DataTemplate>
            </HierarchicalDataTemplate.ItemTemplate>
        </HierarchicalDataTemplate>
    </TreeView.Resources>
</TreeView>

Вы передаете Автомобили самому элементу управления TreeView, чтобы у него был источник предметов.

<TreeView ItemsSource="{Binding Cars}">

Затем вы определяете шаблон через ресурсы. В вашем случае это HierarchicalDataTemplate, так как у автомобилей есть другой уровень.

<TreeView.Resources>
    <HierarchicalDataTemplate DataType="{x:Type local:Car}" ItemsSource="{Binding Features}">
    </HierarchicalDataTemplate>
</TreeView.Resources>

Важно сказать, что ваш HierarchicalDataTemplate DataType - Car, а затем вам также нужно определить ItemsSource. По сути, вы говорите WPF: всякий раз, когда вы сталкиваетесь с типом автомобиля, выведите иерархию и используйте набор функций, которые вы можете найти в типе автомобиля.

После этого вы определяете фактический контент. Контент представляет собой TextBlock, который показывает свойство Make из типа Car, а затем мы определяем HierarchicalDataTemplate ItemTemplate. Итак, здесь мы говорим WPF: как только вы создадите Car, убедитесь, что вы также расположили дочерний узел. В вашем случае нет конкретного свойства c для привязки, поскольку это список строк.

<TextBlock Text="{Binding Make}"/>
<HierarchicalDataTemplate.ItemTemplate>
    <DataTemplate>
        <TextBlock Text="{Binding}"/>
    </DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
...