0

我有一个使用 hiarchialdatabinding 由可观察集合填充的 WPF TreeView 我需要访问可观察集合中的项目或用于填充它的数据库。一个示例用例是用户右键单击树视图项以添加子组。我显然需要访问它的父母来添加孩子。有什么建议么?我好失落。。

我不能只编辑树视图项目本身,因为然后更改不会反映回我的数据库

数据库代码:

[Serializable]
public class LoginGroup
{
    public string Name { get; set; }
    public Guid ID { get; set; }
    public List<Login> LoginItems = new List<Login>();
    public List<LoginGroup> Children { get; set; }
}

public static ObservableCollection<LoginGroup> _GroupCollection = new  ObservableCollection<LoginGroup>();

public ObservableCollection<LoginGroup> GroupCollection
{
    get { return _GroupCollection; }
}

树视图:

<TreeView x:Name="groupView" Width="211" TreeViewItem.Selected="OnTreeItemSelected" DockPanel.Dock="Left" Height="Auto" ItemsSource="{Binding GroupCollection}" >
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding Path=Children}">
            <TextBlock Text="{Binding Path=Name}" />
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>
4

3 回答 3

0

您可以将其SelectedItem转换为LoginGroup

LoginGroup selectedGroup = (LoginGroup)groupView.SelectedItem;
于 2012-05-22T07:35:11.130 回答
0

您应该使用 TreeView 的 ItemContainer 样式。
这是示例 TreeNode 视图模型:

public class TreeNode : ViewModel
{
    public TreeNode()
    {
        this.children = new ObservableCollection<TreeNode>();

        // the magic goes here
        this.addChildCommand = new RelayCommand(obj => AddNewChild());
    }

    private void AddNewChild()
    {
        // create new child instance
        var child = new TreeNode 
        { 
            Name = "This is a new child node.",
            IsSelected = true // new child should be selected
        };

        // add it to collection
        children.Add(child);

        // expand this node, we want to look at the new child node
        IsExpanded = true;
    }

    public String Name
    {
        get { return name; }
        set
        {
            if (name != value)
            {
                name = value;
                OnPropertyChanged("Name");
            }
        }
    }
    private String name;

    public Boolean IsSelected
    {
        get { return isSelected; }
        set
        {
            if (isSelected != value)
            {
                isSelected = value;
                OnPropertyChanged("IsSelected");
            }
        }
    }
    private Boolean isSelected;

    public Boolean IsExpanded
    {
        get { return isExpanded; }
        set
        {
            if (isExpanded != value)
            {
                isExpanded = value;
                OnPropertyChanged("IsExpanded");
            }
        }
    }
    private Boolean isExpanded;

    public ObservableCollection<TreeNode> Children
    {
        get { return children; } 
    }
    private ObservableCollection<TreeNode> children;

    public ICommand AddChildCommand
    {
        get { return addChildCommand; }
    }
    private RelayCommand addChildCommand;
}

一些评论:

  • ViewModel 是 INotifyPropertyChanged 接口的任何基本实现。
  • RelayCommand(又名 DelegateCommand)是用于 MVVM 方法的 ICommand 实现。

这是视图:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <TreeView ItemsSource="{Binding}">
        <TreeView.ItemContainerStyle>
            <!-- Let's glue our view models with the view! -->
            <Style TargetType="{x:Type TreeViewItem}">
                <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
                <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
                <Setter Property="ContextMenu">
                    <Setter.Value>
                        <ContextMenu>
                            <!-- Here's menu item, which is responsible for adding new child node -->
                            <MenuItem Header="Add child..." Command="{Binding AddChildCommand}" />
                        </ContextMenu>
                    </Setter.Value>
                </Setter>
            </Style>
        </TreeView.ItemContainerStyle>
        <TreeView.ItemTemplate>
            <HierarchicalDataTemplate ItemsSource="{Binding Children}">
                <TextBlock Text="{Binding Name}"/>
            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>
    </TreeView>
</Window>

...和示例数据上下文初始化:

    public MainWindow()
    {
        InitializeComponent();
        DataContext = new ObservableCollection<TreeNode>
        {
            new TreeNode { Name = "Root", IsSelected = true }
        };
    }

希望这可以帮助。

更新
当然,您也必须将子节点公开为 ObservableCollection。否则,对节点集合所做的更改将不会反映。

于 2012-05-22T07:39:51.033 回答
0

您无法反映属性的更改,因为它们无法“注意到”它们已被编辑。LoginGroup您需要继承DependencyObject或实施INotifyPropertyChanged

于 2012-05-22T07:44:53.363 回答