WPF TreeView, привязка TwoWay для IsExpanded не влияет на код GUI из C# - PullRequest
0 голосов
/ 29 января 2020

Я пытаюсь создать TreeView, который может отображать элементы в иерархии дерева. Я хочу иметь возможность использовать код (C#) для раскрытия и свертывания TreeViewItems в TreeView через свойства, связанные с ObservableCollection.

Я связал свойство моего класса с IsExpanded, и кажется, работать, если я установлю его ДО установки элемента ItemSource в дереве - вновь созданная иерархия будет получена предварительно развернутой.

Но если я нажму кнопку, которая устанавливает IsExpanded для элемента в коллекции, она не развернется и не свернется элементы дерева в GUI.

Вот скверный скриншот программы. Папки были созданы вручную в процедуре инициализации.

Really ugly screenshot, so you get an idea of what we're dealing with.

Вот дерево TreeView в главном окне:

<TreeView x:Name="TheProjectTree" Margin="5" BorderBrush="{x:Null}" ItemsSource="{Binding DataSet}">
    <TreeView.ItemContainerStyle>
        <Style TargetType="{x:Type TreeViewItem}">
            <Setter Property="IsExpanded" Value="{Binding Path=IsExpanded, Mode=TwoWay}" />
            <!--<EventSetter Event="Expanded" Handler="TheProjectTreeItem_Expanded" />-->
        </Style>
    </TreeView.ItemContainerStyle>
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding nodes}">
            <StackPanel Orientation="Horizontal">
                <Image Source="{Binding Path=Icon}" Height="16"/>
                <TextBlock Text=" " />
                <TextBlock Text="{Binding Path=Name}" />
                <TextBlock Text=" (" />
                <TextBlock Text="{Binding Path=Type}" />
                <TextBlock Text=")" />
            </StackPanel>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

Вот класс MyProject, который имеет структуры данных:

using System.Collections.ObjectModel;

namespace Project_X
{
    public class MyProject
    {
        public ObservableCollection<MyNode> nodes;

        public MyProject()
        {

        }

        public void Initialize()
        {
            nodes = new ObservableCollection<MyNode>();
            nodes.Add(new MyNode("Untitled Project", "Project"));
            AddFolder("0. Initialize");
            AddFolder("1. Reset");
            AddFolder("2. Migrate");
        }

        public void AddFolder(string folderName)
        {
            nodes[0].nodes.Add(new MyProject.MyNode(folderName, "Folder"));
        }

        public class MyNode
        {
            public string Name { get; set; }
            public string Type { get; set; }
            public bool IsExpanded { get; set; }
            public ObservableCollection<MyNode> nodes { get; set; }
            public MyNode(string theName, string theType)
            {
                Name = theName;
                Type = theType;
                nodes = new ObservableCollection<MyNode>();
            }
            public string Icon
            {
                get
                {
                    if (Type == "Project")
                        return "./graphics/icon_projectTree_small.png";
                    else if (Type == "Folder")
                        return "./graphics/icon_projectTree_small.png";
                    else if (Type == "Object")
                        return "./graphics/icon_projectTree_small.png";
                    else if (Type == "SQL")
                        return "./graphics/icon_projectTree_small.png";
                    else if (Type == "Text")
                        return "./graphics/icon_projectTree_small.png";
                    return "./graphics/icon_projectTree_small.png";
                }
            }
        }
    }
}

И, наконец, вот небольшая тестовая процедура, которую я могу вызвать с помощью кнопки тестирования.

private void NewProject()
{
    Project = new MyProject();                      // fire up the main project variable!
    Project.Initialize();                           // give it some dummy data!
    Project.nodes[0].IsExpanded = true;             // pre-expand the top-level project node
    TheProjectTree.ItemsSource = Project.nodes;     // assign the data set to the tree in the main window



    Project.AddFolder("test");                      // this works! adding new folders to the collection will show up in the GUI
    Project.nodes[0].IsExpanded = true;             // this does NOT work! it should collapse the top-levl project node in the tree, but it doesn't
}

Я бы очень хотел Я ценю это, если бы ты мог побить меня знаниями. Я обычно работаю в SQL, C# и. NET - не моя сильная сторона. Я провел весь вечер, пытаясь обернуть голову вокруг MVVM, и теперь я чувствую себя по-настоящему вонючим программистом!

Ответы [ 2 ]

2 голосов
/ 29 января 2020

Реализация INotifyPropertyChanged интерфейса для вашего MyNode класса. Который уведомляет, что значение свойства изменилось.

public class MyNode : INotifyPropertyChanged
{
    private bool isExpanded;

    public string Name { get; set; }
    public string Type { get; set; }
    public bool IsExpanded
    {
        get => isExpanded;
        set
        {
            isExpanded = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsExpanded)));
        }
    }
    public ObservableCollection<MyNode> nodes { get; set; }
    public MyNode(string theName, string theType)
    {
        Name = theName;
        Type = theType;
        nodes = new ObservableCollection<MyNode>();
    }

    public event PropertyChangedEventHandler PropertyChanged;
}
1 голос
/ 29 января 2020

Ваш класс MyNode должен реализовать INotifyPropertyChanged , чтобы Gui знал, что свойство изменилось. Затем в установщике свойства IsExpanded вам нужно будет вызвать объяснение NotifyPropertyChanged по данной ссылке.

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