当前位置: 首页 > 知识库问答 >
问题:

当子项是相同的对象时,在treeview中获取父注释

颜镜
2023-03-14

我有一个树视图,在xaml createt树视图项中有相同的树视图。其中一个音符有一个ObservableCollection作为ItemSource。这很有魅力。但现在我希望列表中的每一项都有相同的注释(以便更好地组织)。所以我这样做:

这是列表的HierarchycalDataTemplate

<HierarchicalDataTemplate DataType="{x:Type classes:Connection}" ItemsSource="{Binding Source={StaticResource ConnectionChilds}}" >
    <TextBlock Text="{Binding DisplayName}" />
</HierarchicalDataTemplate>

和ItemsSource:

<collections:ArrayList x:Key="ConnectionChilds">
    <classes:TreeItemObject ItemsSourcePath="Child1" />
    <classes:TreeItemObject ItemsSourcePath="Child2" />
    <classes:TreeItemObject ItemsSourcePath="Child3" />
</collections:ArrayList>

TreeItemObject是一个简单的类:

public class TreeItemObject
{
    public string ItemsSourcePath { get; set; }
}

最后但并非最不重要的是TreeItemObject的HierarchycalDataTemplate:

<DataTemplate DataType="{x:Type classes:TreeItemObject}">
    <TextBlock Margin="5,0" Text="{Binding Path=ItemsSourcePath}"/>
</DataTemplate>

像这样

Connection 1
    Child1
    Child2
    Child3
Connection 2
    Child1
    Child2
    Child3
Connection 3
    Child1
    Child2
    Child3

工作顺利。但是现在如果我选择连接2\Child3,我得到了相同的对象,如连接1\Child3或连接3\Child3。好的有意义,因为基于相同的对象。在这种情况下,我没有机会在OnSseltedItemChanged上找到父注释。

因为如果我用这个扩展类搜索。我只收到第一张扩展的连接说明。

http://social.msdn.microsoft.com/Forums/silverlight/en-US/84cd3a27-6b17-48e6-8f8a-e5737601fdac/treeviewitemcontainergeneratorcontainerfromitem-returns-null?forum=silverlightnet

有没有办法在树视图中找到真正的父母?

共有3个答案

巫培
2023-03-14

很难从treeView项中获取父级,因此我所做的是,我拥有父级类型的父级的成员属性,该属性保存对父级的引用,如下所示

public class FileSystem :NotifyChange, IEnumerable
{
#region Private members
private ObservableCollection<FileSystem> subDirectoriesField;
#endregion

#region Public properties
/// <summary>
/// Gets and sets all the Files in the current folder
/// </summary>
public ObservableCollection<FileSystem> SubDirectories
{
    get
    {
        return subDirectoriesField;
    }
    set
    {
        if (subDirectoriesField != value)
        {
            subDirectoriesField = value;
            RaisePropertyChanged("SubDirectories");
        }
    }
}
/// <summary>
/// Gets or sets name of the file system 
/// </summary>
public string Name
{
    get;
    set;
}
/// <summary>
/// Gets or sets full path of the file system
/// </summary>
public string FullPath
{
    get;
    set;
}
/// <summary>
/// object of parent, null if the current node is root
/// </summary>
public FileSystem Parent
{
    get;
    set;
}
public FileSystem(string fullPath, FileSystem parent)
{
    Name = fullPath != null ? fullPath.Split(new char[] { System.IO.Path.DirectorySeparatorChar },
        StringSplitOptions.RemoveEmptyEntries).Last()
    FullPath = fullPath;
    Parent = parent;
    AddSubDirectories(fullPath);
}

public IEnumerator GetEnumerator()
{
    return SubDirectories.GetEnumerator();
}

private void AddSubDirectories(string fullPath)
{
    string[] subDirectories = Directory.GetDirectories(fullPath);
    SubDirectories = new ObservableCollection<FileSystem>();
    foreach (string directory in subDirectories)
    {
        SubDirectories.Add(new FileSystem(directory, this));
    }
}
}

我的viewModel如下所示

public class ViewModel:NotifyChange
{
  private ObservableCollection<FileSystem> directories;
  public ObservableCollection<FileSystem> Directories
  {
    get
    {
        return directoriesField;
    }
    set
    {
        directoriesField = value;
        RaisePropertyChanged("Directories");
    }
  }
  public ViewModel()
  {
   //The below code has to be moved to thread for better user expericen since when UI is loaded it might not respond for some time since it is looping through all the drives and it;s directories
   Directories=new  ObservableCollection<FileSystem>();
   Directories.Add(new FileSystem("C:\\", null);
   Directories.Add(new FileSystem("D:\\", null);
   Directories.Add(new FileSystem("E:\\", null);
  }
}

因为每个孩子都知道;现在您可以往回遍历,根节点父节点将为空

Xmal将具有以下特性

 <TreeView Grid.Row="1" Background="Transparent" ItemsSource="{Binding Directories}" Margin="0,10,0,0" Name="FolderListTreeView"
            Height="Auto" HorizontalAlignment="Stretch" Width="300"  >
            <TreeView.Resources>
                <HierarchicalDataTemplate DataType="{x:Type local:FileSystem}" ItemsSource="{Binding SubDirectories}">
                    <Label Content="{Binding Path= Name}" Name="NodeLabel" />
                </HierarchicalDataTemplate>
            </TreeView.Resources>
        </TreeView>

希望这对你有帮助

华和悦
2023-03-14

我认为您唯一的选择是在将子节点添加到TreeView之前克隆它们,至少允许子节点之间存在二进制差异。

如果执行此操作,则无需处理OnSseltedItemChanged事件并遍历对象图,而是向其子级中的每个子级添加父级的Weak参考。这将允许您立即引用来自孩子的父,也允许。net来正确清理对象图。

从SelectedItemChanged事件处理程序使用WeakReference属性的示例如下

private void TreeView_OnSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
    var treeView = sender as TreeView;
    var item = treeView.SelectedItem as TreeItemObject;
    if (item.Parent.IsAlive)
    {
        var parent = item.Parent.Target;
    }
}

为了简洁起见,我删除了异常管理和空检查。

我希望这有帮助。

宇文鸣
2023-03-14

我个人不喜欢在转换器中创建克隆的想法,但我不知道你问题的全部范围。因此,使用您在这里展示的内容,我们可以通过多值转换器实现对每个TreeItemObject的父对象的分配。

WPF有一个很棒的特性,叫做多重绑定。它将一个或多个源值处理为单个目标。为此,它需要一个多值转换器。

因此,将TreeItemObject更改为

public class TreeItemObject
{
    public string ItemsSourcePath { get; set; }
    public WeakReference Parent { get; set; }
}

连接类型的HierarchycalDataTemplate将变为

<HierarchicalDataTemplate DataType="{x:Type classes:Connection}">
    <HierarchicalDataTemplate.ItemsSource>
        <MultiBinding Converter="{StaticResource items2Clones}">
            <Binding Source="{StaticResource ConnectionChilds}" />
            <Binding />
        </MultiBinding>
    </HierarchicalDataTemplate.ItemsSource>
    <TextBlock Text="{Binding DisplayName}" />
</HierarchicalDataTemplate>

基于上述绑定,要在转换器中设置父级,Convert中的Convert方法将如下所示

public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
    var destinationItems = new Collection<TreeItemObject>();

    var items = values[0] as Collection<TreeItemObject>;
    var parent = values[1] as Connection;

    // null checks are required here for items and parent

    foreach (var item in items)
    {
        var destinationItem = item.Clone(); // Assumed extension method
        destinationItem.Parent = new WeakReference(parent);
        destinationItems.Add(destinationItem);
    }

    return destinationItems;
}

最后,SseltedItemChanged事件处理程序类似于

private void TreeView_OnSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
    var item = (TreeItemObject)e.NewValue;
    if ((item != null) && (item.Parent != null) && (item.Parent.IsAlive))
    {
        // do stuff - Console.WriteLine(((Connection)item.Parent.Target).DisplayName);
    }
}

为了简洁起见,我删除了异常管理和一些空检查。

我希望这有帮助

 类似资料:
  • 问题内容: 我有以下(嵌套)对象: 接下来,我要做的就是像这样引用子对象: 现在,我想做的就是从变量中获取对对象的引用。就像是: 这可能吗? 问题答案: 否。无法知道它来自哪个对象。 而这两个只是有同一个对象的引用。 您也可以这样做: 您现在有三个引用,和,同一个对象。它们都不是特别的。

  • 父类: 子电话对象(第一级): 我正在尝试获取person对象,其phone对象类型为home,其编号应包含“888”。 从上面的流代码,我能够得到手机对象。但是如何在相同的函数中获得该电话对象的父对象呢?。 我尝试了这种方式,我得到null不匹配的对象。

  • 问题内容: 假设我有这个标记: 我有这个jQuery: 单击该子项时,如何获得子项相对于其父项的索引? 例如,当您单击“步骤1”时,应弹出带有“ 0”的。 问题答案: 但是,与其为每个列表项附加一个单击处理程序,不如(在性能方面)更好地使用如下所示: 在jQuery 1.7+中,您应该使用。下面的示例将事件绑定到元素,就像委托事件一样工作:

  • 我在http://neo4j.com/docs/ogm/java/stable/遵循Neo4j OGM指南 对于关系实体,我们需要有一个开始节点和一个结束节点。我对这个例子做了一点修改(使它像这样更简单)- 现在,当我尝试保存这个在Neo4j,它工作正常。但是在我的场景中,StartNode和EndNode对象的类型是相同的- 当我尝试使用- 学生、课程和注册对象被保存,但两个MyObject和M

  • 我有https://github.com/javers/javers/issues/98中描述的类似用例。 在下面的代码中,当我更新dependent对象并提交Employee bob时,我希望对dependent的更改从JQL query 完整代码: 我得到以下输出。这缺少从属名称更改(Ram到Ramsey)。 谢谢

  • 问题内容: 在Python中,是否可以从Bar本身获取包含另一个对象Bar的对象(例如Foo)?这是我的意思的一个例子 这可能吗?谢谢! 问题答案: 传递对Bar对象的引用,如下所示: 编辑: 正如@thomleo指出的那样,这可能导致垃圾回收问题。建议的解决方案位于http://eli.thegreenplace.net/2009/06/12/safely- using-destructors-