Silverlight树视图:保存展开/折叠状态

发布于 2024-12-06 22:28:35 字数 1246 浏览 0 评论 0原文

我在 Silverlight 4 中使用分层树视图。根据用户的操作,可以经常清除和重建该树。发生这种情况时,树默认会折叠,从用户的角度来看,这可能很烦人。

因此,我想以某种方式保存哪些节点已展开,以便我可以在清除并重新加载树后恢复树的视觉状态。

我的树视图是这样实现的:

xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
xmlns:controls2="clr-namespace:System.Windows;assembly=System.Windows.Controls"

<controls:TreeView x:Name="Tree"
    ItemsSource="{Binding Source={StaticResource ViewModel}, Path=TreeStructure, Mode=OneWay}"
    ItemTemplate="{StaticResource hierarchicalTemplate}" />

<controls2:HierarchicalDataTemplate x:Key="hierarchicalTemplate" ItemsSource="{Binding Children}">
        <TextBlock Text="{Binding Value.DisplayName}">
</controls2:HierarchicalDataTemplate>

我的树视图的 ItemsSource 绑定在 ObservableCollection TreeStructure 上;

Node 是一个包装类,看起来像这样:

public class Node
{
    public object Value { get; private set; }

    public ObservableCollection<Node> Children { get; private set; }

    public Node(object value)
    {
        Value = value;
        Children = new ObservableCollection<Node>();
    }
 }

非常标准的东西。我看到了一些 WPF 的解决方案,但我可以找到有关 Silverlight 树视图的任何内容...

有什么建议吗?

谢谢!

I'm using a hierarchical tree view in Silverlight 4. This tree can be cleared and rebuilded quite often, depending on the user's actions. When this happends, the tree is collapsed by default, which can be annoying from a user perspective.

So, I want to somehow save which nodes are expanded so I can restore the visual state of my tree after it is clear and reloaded.

My treeview is implemented like this:

xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
xmlns:controls2="clr-namespace:System.Windows;assembly=System.Windows.Controls"

<controls:TreeView x:Name="Tree"
    ItemsSource="{Binding Source={StaticResource ViewModel}, Path=TreeStructure, Mode=OneWay}"
    ItemTemplate="{StaticResource hierarchicalTemplate}" />

<controls2:HierarchicalDataTemplate x:Key="hierarchicalTemplate" ItemsSource="{Binding Children}">
        <TextBlock Text="{Binding Value.DisplayName}">
</controls2:HierarchicalDataTemplate>

ItemsSource of my treeview is bound on an ObservableCollection TreeStructure;

Node is a wrapper class that looks like that:

public class Node
{
    public object Value { get; private set; }

    public ObservableCollection<Node> Children { get; private set; }

    public Node(object value)
    {
        Value = value;
        Children = new ObservableCollection<Node>();
    }
 }

Pretty standard stuff. I saw some solutions for WPF, but I can find anything for the Silverlight tree view...

Any suggestions?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

梦忆晨望 2024-12-13 22:28:35

考虑到您将数据实现为树的方式,为什么不将“TreeViewItem.IsExpanded”依赖属性绑定到您自己的节点上的 bool 属性呢?

它至少需要是一个 INotifyPropertyChanged 属性,因此 Node 需要实现 INotifyPropertyChanged。

在 Silverlight 5 中,您只需设置这样的样式即可绑定到 IsExpanded 属性:

<Style TargetType="sdk:TreeViewItem" x:Key="itemStyle">
    <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
</Style>

并使用

ItemContainerStyle="{Binding Source={StaticResource itemStyle}}"

在 Silverlight 4 中,有许多解决方法。

Given the way you are implementing your data as a tree, why not bind the 'TreeViewItem.IsExpanded` dependency property to a bool property on your own Node?

It will need to be an INotifyPropertyChanged property at a minimum so Node will need to implement INotifyPropertyChanged.

In Silverlight 5 you can just set a style like this to bind to the IsExpanded property:

<Style TargetType="sdk:TreeViewItem" x:Key="itemStyle">
    <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
</Style>

And use with

ItemContainerStyle="{Binding Source={StaticResource itemStyle}}"

In Silverlight 4 there are a number of workarounds.

情何以堪。 2024-12-13 22:28:35

这是我在 TreeViewItem.IsExpanded 属性上绑定的操作。首先,我在 Node 类中添加了 IsExpanded 属性。

public class Node : INotifyPropertyChanged
{
    public object Value { get; private set; }

    public ObservableCollection<Node> Children { get; private set; }

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

    public Node(object value)
    {
        Value = value;
        Children = new ObservableCollection<Node>();
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
 }

之后,我对 TreeView 和 TreeViewItem 控件进行了子类化(我丢失了树视图上的自定义主题,但无论如何......)

public class BindableTreeView : TreeView
{
    protected override DependencyObject GetContainerForItemOverride()
    {
        var itm = new BindableTreeViewItem();
        itm.SetBinding(TreeViewItem.IsExpandedProperty, new Binding("IsExpanded") { Mode = BindingMode.TwoWay });

        return itm;
    }
}

public class BindableTreeViewItem : TreeViewItem
{
    protected override DependencyObject GetContainerForItemOverride()
    {
        var itm = new BindableTreeViewItem();
        itm.SetBinding(TreeViewItem.IsExpandedProperty, new Binding("IsExpanded") { Mode = BindingMode.TwoWay });

        return itm;
    }
}

在我的 XAML 中,我只需使用 BindableTreeView 而不是 TreeView,并且它可以工作。

Here's what I did to bind on the TreeViewItem.IsExpanded property. First, I added an IsExpanded property in my Node class.

public class Node : INotifyPropertyChanged
{
    public object Value { get; private set; }

    public ObservableCollection<Node> Children { get; private set; }

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

    public Node(object value)
    {
        Value = value;
        Children = new ObservableCollection<Node>();
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
 }

After that, I subclassed the TreeView and TreeViewItem controls (I lose the custom theme on my treeview, but whatever...)

public class BindableTreeView : TreeView
{
    protected override DependencyObject GetContainerForItemOverride()
    {
        var itm = new BindableTreeViewItem();
        itm.SetBinding(TreeViewItem.IsExpandedProperty, new Binding("IsExpanded") { Mode = BindingMode.TwoWay });

        return itm;
    }
}

public class BindableTreeViewItem : TreeViewItem
{
    protected override DependencyObject GetContainerForItemOverride()
    {
        var itm = new BindableTreeViewItem();
        itm.SetBinding(TreeViewItem.IsExpandedProperty, new Binding("IsExpanded") { Mode = BindingMode.TwoWay });

        return itm;
    }
}

In my XAML, I just have to use BindableTreeView instead of TreeView, and it works.

做个少女永远怀春 2024-12-13 22:28:35

诀窍是使用 此处。然后您的 XAML 将如下所示。请务必仔细复制我下面的内容。

<sdk:TreeView.ItemContainerStyle>
    <Style TargetType="sdk:TreeViewItem">
        <Setter Property="local:SetterValueBindingHelper.PropertyBinding">
            <Setter.Value>
                <local:SetterValueBindingHelper>
                    <local:SetterValueBindingHelper Property="IsSelected" Binding="{Binding Mode=TwoWay, Path=IsSelected}"/>
                    <local:SetterValueBindingHelper Property="IsExpanded" Binding="{Binding Mode=TwoWay, Path=IsExpanded}"/>
                </local:SetterValueBindingHelper>
            </Setter.Value>
        </Setter>
    </Style>
</sdk:TreeView.ItemContainerStyle>

该语法与您在 WPF 中使用的语法并不完全相同,但它可以工作,而且工作得很好!

The trick is to use SetterValueBindingHelper from here. Then your XAML will look like the following. Make sure you carefully copy what I have below.

<sdk:TreeView.ItemContainerStyle>
    <Style TargetType="sdk:TreeViewItem">
        <Setter Property="local:SetterValueBindingHelper.PropertyBinding">
            <Setter.Value>
                <local:SetterValueBindingHelper>
                    <local:SetterValueBindingHelper Property="IsSelected" Binding="{Binding Mode=TwoWay, Path=IsSelected}"/>
                    <local:SetterValueBindingHelper Property="IsExpanded" Binding="{Binding Mode=TwoWay, Path=IsExpanded}"/>
                </local:SetterValueBindingHelper>
            </Setter.Value>
        </Setter>
    </Style>
</sdk:TreeView.ItemContainerStyle>

The syntax isn't exactly like what you would use in WPF, but it works and it works well!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文