2015-03-22 2 views
1

При использовании objectListView treeListView если у меня есть расширялся treeListView и нажал на одну из детей в одной из колонн, как я:Найти родитель в objectlistview treelistview

  1. Найти родитель этого ребенка ?
  2. Найдите значение/текст родительской строки для расширенного столбца?

Этот пример может помочь объяснить, что я имею в виду.

public partial class Form1 : Form 
{ 

    List<Contract> list; 
    public Form1() 
    { 
     InitializeComponent(); 

     list = new List<Contract>(); 
     list.Add(new Contract("A", 1)); 
     list.Add(new Contract("B", 2)); 
     foreach (Contract c in list) 
     { 
      this.treeListView1.CanExpandGetter = delegate(object x) 
      { 
       if (x is Contract) 
       { 
        return (((Contract)x).Children.Count > 0); 
       } 
       else 
       { 
        return false; 
       } 
      }; 
      this.treeListView1.ChildrenGetter = delegate(object x) 
      { 
       Contract contrat = x as Contract; 
       return contrat.Children; 
      }; 

      column1.AspectGetter = delegate(object x) 
      { 
       if (x is Contract) 
       { 
        return ((Contract)x).Name; 
       } 
       else 
       { 
        return " "; 
       } 
      }; 

      column2.AspectGetter = delegate(object x) 
      { 
       if (x is Contract) 
       { 
        return ((Contract)x).Value; 
       } 
       else 
       { 
        Double d = (Double)x; 
        return d.ToString(); 
       } 
      }; 

      this.treeListView1.AddObject(c); 
     } 
    } 

    private void treeListView1_CellClick(object sender, BrightIdeasSoftware.CellClickEventArgs e) 
    { 
     //NOT SURE WHAT TO DO HERE 

    } 

    public void WriteLine(String s) 
    { 
     if (this.richTextBox1.TextLength > 0) 
     { 
      this.richTextBox1.AppendText(Environment.NewLine); 
     } 
     this.richTextBox1.AppendText(s); 
    } 
} 

public class Contract 
{ 
    public string Name { get; set;} 
    public Double Value { get; set; } 
    public List<Double> Children {get; set;} 

    public Contract(string name, Double value) 
    { 
     Name = name; 
     Value = value; 
     Children = new List<Double>(); 
     Children.Add(2); 
     Children.Add(3); 
    } 
} 

Здесь на события CellClick Я хочу, чтобы получить как родителя и независимо от значения родителя в column1 есть.

ответ

2

Вы делаете это самостоятельно, добавляя простые двойные значения в качестве дочерних элементов. Эти предметы не имеют возможности найти настоящего родителя.

Если вы можете изменить свой класс контракта, вы можете изменить его как тип TreeNode, а его дети всегда ссылаются на сам контракт. На cell_click вы можете просто получить e.Model, а затем получить родителя, если это не сам контракт.

Если вы хотите, чтобы сделать его более гибким для будущих реализаций, которые вы хотите сделать, вы могли бы изменить договор таким образом, что она соответствует структуре дерева

Интерфейс для этого говорит, что ваш узел есть дети

public interface ITreeNode 
{ 
    IList<ITreeChild> Children { get; } 
} 

интерфейс, который говорит, что он имеет родителя

public interface ITreeChild 
{ 
    object Parent { get; set; } 
} 

корневой узел, который хранит родительскую ссылку на ребенке Пункты до даты

public abstract class TreeRoot : ITreeNode, IDisposable 
{ 
    private readonly IList<ITreeChild> children = new ObservableCollection<ITreeChild>(); 
    public IList<ITreeChild> Children 
    { 
     get 
     { 
      return children; 
     } 
    } 

    protected virtual void OnChildCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
    { 
     if (e.OldItems != null) 
     { 
      foreach (var item in e.OldItems) 
      { 
       var treeItem = item as ITreeChild; 
       if (treeItem == null) 
       { 
        continue; 
       } 
       treeItem.Parent = null; 
      } 
     } 
     if (e.NewItems != null) 
     { 
      foreach (var item in e.NewItems) 
      { 
       var treeItem = item as ITreeChild; 
       if (treeItem == null) 
       { 
        continue; 
       } 
       treeItem.Parent = this; 
      } 
     } 
    } 

    private bool isDisposed = false; 
    public virtual void Dispose(bool disposing) 
    { 
     if (!disposing) 
     { 
      return; 
     } 
     if (isDisposed) 
     { 
      return; 
     } 
     isDisposed = true; 
     Destroy(); 
    } 

    public void Dispose() 
    { 
     Dispose(true); 
    } 

    public void Init() 
    { 
     var colc = Children as INotifyCollectionChanged; 
     if (colc != null) 
     { 
      colc.CollectionChanged += OnChildCollectionChanged; 
     } 
    } 

    public void Destroy() 
    { 
     Children.Clear(); 
     var colc = Children as INotifyCollectionChanged; 
     if (colc != null) 
     { 
      colc.CollectionChanged -= OnChildCollectionChanged; 
     } 
    } 
} 

и TreeNode на основе этого TreeRoot

public class TreeNode : TreeRoot, ITreeChild 
{ 
    public string Name 
    { 
     get; 
     set; 
    } 

    private object parent; 
    public object Parent 
    { 
     get 
     { 
      return parent; 
     } 
     set 
     { 
      parent = value; 
     } 
    } 

    public TreeNode() 
     : base() 
    { 
     Init(); 
    } 
} 

Очень простой TreeChild (это было больше используется в качестве теста)

public class TreeChild : ITreeChild 
{ 
    public object Parent 
    { 
     get;set; 
    } 
} 

А потом в конце концов, ваш контракт

public class Contract : TreeNode 
{ 
    public Double Value { get; set; } 

    public Contract() 
     : base() 
    { 
    } 
} 

, который может содержать все виды ITreeChild, поэтому сделать его DoubleChild

public class DoubleChild : TreeChild 
{ 
    private double value; 
    public double Value 
    { 
     get 
     { 
      return value; 
     } 
     set 
     { 
      this.value = value; 
     } 
    } 
} 

А потом построить свой TreeListView:

protected void AddDefault(TreeNode c) 
{ 
    c.Children.Add(new DoubleChild { Value = 3 }); 
    c.Children.Add(new DoubleChild { Value = 4 }); 
} 

TreeListView treeListView1; 

public Form1() 
{ 
    InitializeComponent(); 
    treeListView1 = new TreeListView(); 
    treeListView1.CellClick += treeListView1_CellClick; 
    OLVColumn columnName = new OLVColumn(); 
    columnName.AspectGetter = (obj) => 
    { 
     var node = obj as TreeNode; 
     if (node != null) 
     { 
      return node.Name; 
     } 
     return " "; 
    }; 
    OLVColumn columnValue = new OLVColumn("Value", "Value"); 
    treeListView1.Columns.Add(columnName); 
    treeListView1.Columns.Add(columnValue); 
    TreeNode rootContract = new TreeNode() { Name = "All Contracts" }; 
    Contract childContract1 = new Contract() { Name = "A", Value = 2 }; 
    Contract childContract2 = new Contract() { Name = "B", Value = 3 }; 
    AddDefault(childContract1); 
    AddDefault(childContract2); 
    rootContract.Children.Add(childContract1); 
    rootContract.Children.Add(childContract2); 
    AddDefault(rootContract); 
    treeListView1.ParentGetter = (obj) => 
    { 
     var child = obj as ITreeChild; 
     if (child == null) 
     { 
      return null; 
     } 
     return child.Parent; 
    }; 
    treeListView1.ChildrenGetter = (obj) => 
    { 
     var child = obj as ITreeNode; 
     if (child == null) 
     { 
      return null; 
     } 
     return child.Children; 
    }; 

    treeListView1.CanExpandGetter = (obj) => 
    { 
     return obj is ITreeNode && ((ITreeNode)obj).Children.Count > 0; 
    }; 

    treeListView1.AddObject(rootContract); 
    treeListView1.Dock = DockStyle.Fill; 
    this.Controls.Add(treeListView1); 
} 

void treeListView1_CellClick(object sender, CellClickEventArgs e) 
{ 
    if (e.Model is Contract) 
    { 
     // you selected a contract 
    } 
    else 
    { 
     var tree = e.Model as ITreeChild; 
     var parent = tree.Parent; 
     if (parent is Contract) 
     { 
      // selected contract 
     } 
     else 
     { 
      // rootnode 
     } 
    } 
} 

Я знаю, это может быть немного больше работы (я также мог бы сделало это немного сложным, не знаю библиотеки), но это должно работать на ваш usecase

+0

Это возможный способ сделать это, я согласен, и если никакое другое решение не доступно думаю, это будет лучший способ двигаться вперед, он делает много смысла писать так, как вы сделали, следовательно, вверх. Тем не менее, я думаю, что должен быть способ сделать это через objectlistview. Возможно, кто-то, кто знает об этом, мог бы добавить свои мысли. – azuric

+1

У CellClickEventArgs есть только те RowIndex, которые были нажаты, за исключением выбора 'e.ListView.TreeModel.GetNthObject (e.RowIndex)' было так много, что я нашел do-able (я не загружал api либо) – Icepickle

+0

Да, я пробовал rowIndex, но это зависит от того, какой родитель вы расширили. – azuric

1

Это на VB.net, но я просто нашел довольно простое решение. Просто вызовите событие treelistview.getparent. Мой пример показывает это внутри события строки формата, но вы также можете использовать его в выбранном событии.Надеюсь, что это помогает

Private Sub TreeListView1_FormatRow(sender As Object, e As FormatRowEventArgs) Handles TreeListView1.FormatRow 

     Dim parent As myObjectExample = TreeListView1.GetParent(e.Model) 

End Sub 
Смежные вопросы