Как определить, находится ли TreeViewItem в процессе расширения или он уже развернут - PullRequest
0 голосов
/ 01 февраля 2011

У меня следующая проблема. У меня есть некоторые элементы в моем дереве, которые находятся на вершине иерархии. Когда я нажимаю на какой-либо элемент, чтобы развернуть его, загрузка всех элементов в выбранном узле может занять 5 секунд. Как можно показать сообщение «Пожалуйста, подождите ... расширение узла ..» во время этого процесса? Как определить, что элемент все еще расширяется или все вложенные элементы загружены и представлены сейчас?

Я уже задавал очень похожий вопрос здесь Показывать сообщение "Пожалуйста, подождите .." при расширении TreeView в WPF , я даже отмечаю ответ как принятый, но, тем не менее, решение, которое у меня есть сейчас, не является удовлетворительным Диалоговое окно «Пожалуйста, подождите ..» мигает (отображается и закрывается столько раз, сколько вложенных элементов).

1 Ответ

1 голос
/ 01 февраля 2011

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

  1. У вас много элементов, поэтому, когда вы расширяете узел - wpf начинает генерировать контейнеры элементов и помещать их в визуальное дерево. Это может быть раздражающим.
  2. С другой стороны, я предполагаю следующий сценарий - пользователь расширяет элемент узла, и вы отправляете запрос к базе данных / удаленному серверу, который может выполняться некоторое время.

WPF не предоставляет событие BeforeExpand, поэтому вам следует использовать данные просмотра, уведомления об изменении свойств, привязку данных и наблюдаемые коллекции. Я проиллюстрирую это в простом приложении.

Весь подход можно приблизительно описать так:

  • Привязать свойство IsExpanded данных представления к свойству IsExpanded TreeViewItem
  • Слушайте свойство IsExpanded где-то изменились уведомления (может быть в модели)
  • Установить свойство IsLoading (в моем sapmle оно объявлено в данных вида)
  • Запустить задачу, которая заполняет внутренние предметы
  • Сбросить свойство IsLoading
  • Поместите DataTrigger в xaml, который реагирует на свойство IsLoading.

Я разработал класс ViewData для своего элемента дерева с наблюдаемыми свойствами IsExpanded, IsLoaded, наблюдаемой коллекцией дочерних элементов и именем, которое будет отображаться:

public class TreeItem : ObservableObject
{
    public TreeItem (string name)
    {
        this.Name = name;
    }

    public string Name 
    {
        get; 
        private set; 
    }

    private bool _isExpanded;
    public bool IsExpanded
    {
        get
        {
            return this._isExpanded;
        }
        set
        {
            if (this._isExpanded != value)
            {
                this._isExpanded = value;
                this.OnPropertyChanged("IsExpanded");
            }
        }
    }

    private bool _isLoading;
    public bool IsLoading
    {
        get
        {
            return this._isLoading;
        }
        set
        {
            if (this._isLoading != value)
            {
                this._isLoading = value;
                this.OnPropertyChanged("IsLoading");
            }
        }
    }


    private ObservableCollection<TreeItem> _innerItems = new ObservableCollection<TreeItem>();
    public IEnumerable<TreeItem> InnerItems
    {
        get
        {
            return this._innerItems;
        }

    }

    public void LoadInnerItems()
    {
        this.IsLoading = true;
        var sc= SynchronizationContext.Current;
        new Thread(new ThreadStart(() => 
            {
                Thread.Sleep(5000);
                sc.Send(o =>
                    {
                        this._innerItems.Add(new TreeItem("1223"));
                        this._innerItems.Add(new TreeItem("2345"));
                        this._innerItems.Add(new TreeItem("666678"));
                        this.IsLoading = false;
                    }, null);
            }))
            .Start();
    }
}

Следующий шаг заключается в разработке модели презентации. Как вы можете видеть, наша модель слушает событие IsExpanded PropertyChanged и когда оно равно истинному началу. LoadingInnerItems .:

public class SampleModel : ObservableObject
{
    public SampleModel()
    {
        this._items.Add(new TreeItem("AAA"));
        this._items.Add(new TreeItem("BBB"));
        this._items.Add(new TreeItem("CCC"));

        foreach (var i in this._items)
        {
            i.PropertyChanged += new PropertyChangedEventHandler(Item_PropertyChanged);
        }

    }

    void Item_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == "IsExpanded")
        {
            var item = (TreeItem)sender;
            if(item.IsExpanded)
            {
                item.LoadInnerItems();
            }
        }
    }

    private ObservableCollection<TreeItem> _items = new ObservableCollection<TreeItem>();
    public IEnumerable<TreeItem> Items
    {
        get
        {
            return this._items;
        }
    }
}

XAML для нашего TreeView. Когда мы загружаем внутренние элементы - передний план нашего дерева выглядит красным:

<TreeView ItemsSource="{Binding Items}">
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding InnerItems}">
            <TextBlock Text="{Binding Name}"/>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
    <TreeView.ItemContainerStyle>
        <Style TargetType="TreeViewItem">
            <Setter Property="IsExpanded"
                    Value="{Binding IsExpanded, Mode=TwoWay}"/>
            <Setter Property="Foreground"
                    Value="Aqua"/>
            <Style.Triggers>
                <DataTrigger Binding="{Binding IsLoading}"
                             Value="True">
                    <Setter Property="Foreground" 
                            Value="Red"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </TreeView.ItemContainerStyle>
</TreeView>

И не забудьте установить модель как текстовый вид данных в коде:

    public MainWindow()
    {
        InitializeComponent();

        this.Model = new SampleModel();
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...