When using objectListView treeListView if I have a expanded the treeListView and have clicked on one of the children in one of the columns, how do I:
This example may help explain what I mean.
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);
}
}
Here on the CellClick event I want to get both the parent and whatever the value of the parent in column1 is.
You are making it yourself a bit hard by adding simple double values as child items. Those items lack the potential for you to find the real parent.
If you are able to change your Contract class, you could change it as a TreeNode type, with its children always refering to the contract itself. Upon cell_click, you can simply get the e.Model and then get the parent in case it is not a contract itself.
If you want it to make it more flexible for the future implementations you want to make, you could change the Contract in such a way that it conforms to a tree structure
An interface for that says that your node has children
public interface ITreeNode
{
IList<ITreeChild> Children { get; }
}
An interface that says that it has a parent
public interface ITreeChild
{
object Parent { get; set; }
}
A root node that keeps the parent reference in the childItems up to date
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;
}
}
}
and a TreeNode based on this 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();
}
}
A very basic TreeChild (it was more used as a test)
public class TreeChild : ITreeChild
{
public object Parent
{
get;set;
}
}
And then eventually your Contract
public class Contract : TreeNode
{
public Double Value { get; set; }
public Contract()
: base()
{
}
}
which can contain as all kinds of ITreeChild, so make it a DoubleChild
public class DoubleChild : TreeChild
{
private double value;
public double Value
{
get
{
return value;
}
set
{
this.value = value;
}
}
}
And then to construct your 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
}
}
}
I know, it might be a bit more work (i also might have made it a bit to complex, don't know the library), but this should work for your usecase