目标:让我们建立一个树形结构菜单,具体的说用一个TreeView来显示菜单。先看效果图
1、首先我们需要建立一个自定义的TreeView,实现单击事件。
namespace
CustomUIElements
... {
public delegate void NodeClickedEvent(object sender, TreeNode nodeClicked);
public class ClickableTreeNode : TreeNode
...{
ClickableTreeView _parent = null;
public event EventHandler NodeClick;
private bool _needsSetup = false;
public bool NeedsSetup
...{
get ...{ return _needsSetup; }
}
public ClickableTreeNode()
: base()
...{
_needsSetup = true;
}
public new ClickableTreeView TreeView
...{
get ...{ return _parent; }
}
public void SetUp(ClickableTreeView tv)
...{
ClickableTreeView clickable = tv as ClickableTreeView;
if (clickable == null) throw new Exception("The clickable tree node was added to a non-clickable tree view");
_parent = clickable;
// register for the node clicked event, when *a* node gets clicked
clickable.NodeClicked += new NodeClickedEvent(clickable_NodeClicked);
_needsSetup = false;
}
public ClickableTreeNode(ClickableTreeView tv) : base()
...{
ClickableTreeView clickable = tv as ClickableTreeView;
if (clickable == null) throw new Exception("The clickable tree node was added to a non-clickable tree view");
_parent = clickable;
// register for the node clicked event, when *a* node gets clicked
clickable.NodeClicked += new NodeClickedEvent(clickable_NodeClicked);
}
void clickable_NodeClicked(object sender, TreeNode nodeClicked)
...{
// if the node is actually us, then fire the NodeClick event...
if ((nodeClicked as ClickableTreeNode) == this)
...{
if (NodeClick != null)
NodeClick(this, new EventArgs());
}
}
}
public class ClickableTreeView : TreeView
...{
public event NodeClickedEvent NodeClicked;
public ClickableTreeView() : base()
...{
this.MouseClick += new MouseEventHandler(ClickableTreeView_MouseClick);
}
void ClickableTreeView_MouseClick(object sender, MouseEventArgs e)
...{
TreeViewHitTestInfo inf = HitTest(e.X, e.Y);
if (inf.Node == null) return; // didnt click a node...
// we clicked a node, so notify that one was clicked...
if (NodeClicked != null)
NodeClicked(this, inf.Node);
}
}
}
... {
public delegate void NodeClickedEvent(object sender, TreeNode nodeClicked);
public class ClickableTreeNode : TreeNode
...{
ClickableTreeView _parent = null;
public event EventHandler NodeClick;
private bool _needsSetup = false;
public bool NeedsSetup
...{
get ...{ return _needsSetup; }
}
public ClickableTreeNode()
: base()
...{
_needsSetup = true;
}
public new ClickableTreeView TreeView
...{
get ...{ return _parent; }
}
public void SetUp(ClickableTreeView tv)
...{
ClickableTreeView clickable = tv as ClickableTreeView;
if (clickable == null) throw new Exception("The clickable tree node was added to a non-clickable tree view");
_parent = clickable;
// register for the node clicked event, when *a* node gets clicked
clickable.NodeClicked += new NodeClickedEvent(clickable_NodeClicked);
_needsSetup = false;
}
public ClickableTreeNode(ClickableTreeView tv) : base()
...{
ClickableTreeView clickable = tv as ClickableTreeView;
if (clickable == null) throw new Exception("The clickable tree node was added to a non-clickable tree view");
_parent = clickable;
// register for the node clicked event, when *a* node gets clicked
clickable.NodeClicked += new NodeClickedEvent(clickable_NodeClicked);
}
void clickable_NodeClicked(object sender, TreeNode nodeClicked)
...{
// if the node is actually us, then fire the NodeClick event...
if ((nodeClicked as ClickableTreeNode) == this)
...{
if (NodeClick != null)
NodeClick(this, new EventArgs());
}
}
}
public class ClickableTreeView : TreeView
...{
public event NodeClickedEvent NodeClicked;
public ClickableTreeView() : base()
...{
this.MouseClick += new MouseEventHandler(ClickableTreeView_MouseClick);
}
void ClickableTreeView_MouseClick(object sender, MouseEventArgs e)
...{
TreeViewHitTestInfo inf = HitTest(e.X, e.Y);
if (inf.Node == null) return; // didnt click a node...
// we clicked a node, so notify that one was clicked...
if (NodeClicked != null)
NodeClicked(this, inf.Node);
}
}
}
2、我们需要的是建立两个我们自己的类,分别实现IUIElementAdapterFactory和UIElementAdapter<T>。
public
class
ClickableTreeViewAdapterFactory : IUIElementAdapterFactory
... {
IUIElementManagerFactory Members#region IUIElementManagerFactory Members
public IUIElementAdapter GetAdapter(object managedExtension)
...{
if (managedExtension is ClickableTreeNode)
return new ClickableTreeViewAdapter(managedExtension as ClickableTreeNode);
else if (managedExtension is ClickableTreeView)
return new ClickableTreeViewAdapter(managedExtension as ClickableTreeView);
return null;
}
#endregion
IUIElementAdapterFactory Members#region IUIElementAdapterFactory Members
public bool Supports(object uiElement)
...{
if (uiElement is ClickableTreeNode)
return true;
else if (uiElement is ClickableTreeView)
return true;
else
return false;
}
#endregion
}
... {
IUIElementManagerFactory Members#region IUIElementManagerFactory Members
public IUIElementAdapter GetAdapter(object managedExtension)
...{
if (managedExtension is ClickableTreeNode)
return new ClickableTreeViewAdapter(managedExtension as ClickableTreeNode);
else if (managedExtension is ClickableTreeView)
return new ClickableTreeViewAdapter(managedExtension as ClickableTreeView);
return null;
}
#endregion
IUIElementAdapterFactory Members#region IUIElementAdapterFactory Members
public bool Supports(object uiElement)
...{
if (uiElement is ClickableTreeNode)
return true;
else if (uiElement is ClickableTreeView)
return true;
else
return false;
}
#endregion
}
public
class
ClickableTreeViewAdapter: UIElementAdapter
<
ClickableTreeNode
>
... {
private ClickableTreeView _managed = null;
private ClickableTreeNode _managedNode = null;
public ClickableTreeViewAdapter(ClickableTreeView element)
...{
_managed = element;
}
public ClickableTreeViewAdapter(ClickableTreeNode node)
...{
_managedNode = node;
}
protected override void Remove(ClickableTreeNode uiElement)
...{
if (_managed != null)
...{
if (!_managed.IsDisposed)
...{
if (_managed.Nodes.Contains(uiElement))
_managed.Nodes.Remove(uiElement);
}
}
else if (_managedNode != null)
...{
if (!_managedNode.TreeView.IsDisposed)
...{
if (_managedNode.Nodes.Contains(uiElement))
_managedNode.Nodes.Remove(uiElement);
}
}
}
protected override ClickableTreeNode Add(ClickableTreeNode item)
...{
if (_managed != null)
...{
if (item.NeedsSetup)
item.SetUp(_managed);
_managed.Nodes.Add(item);
}
else if (_managedNode != null)
...{
if (item.NeedsSetup)
item.SetUp(_managedNode.TreeView);
_managedNode.Nodes.Add(item);
}
return item;
}
}
... {
private ClickableTreeView _managed = null;
private ClickableTreeNode _managedNode = null;
public ClickableTreeViewAdapter(ClickableTreeView element)
...{
_managed = element;
}
public ClickableTreeViewAdapter(ClickableTreeNode node)
...{
_managedNode = node;
}
protected override void Remove(ClickableTreeNode uiElement)
...{
if (_managed != null)
...{
if (!_managed.IsDisposed)
...{
if (_managed.Nodes.Contains(uiElement))
_managed.Nodes.Remove(uiElement);
}
}
else if (_managedNode != null)
...{
if (!_managedNode.TreeView.IsDisposed)
...{
if (_managedNode.Nodes.Contains(uiElement))
_managedNode.Nodes.Remove(uiElement);
}
}
}
protected override ClickableTreeNode Add(ClickableTreeNode item)
...{
if (_managed != null)
...{
if (item.NeedsSetup)
item.SetUp(_managed);
_managed.Nodes.Add(item);
}
else if (_managedNode != null)
...{
if (item.NeedsSetup)
item.SetUp(_managedNode.TreeView);
_managedNode.Nodes.Add(item);
}
return item;
}
}
3、在初始化阶段注册我们自定义的界面工厂
protected
override
void
AfterShellCreated()
... {
base.AfterShellCreated();
IUIElementAdapterFactoryCatalog catalog = RootWorkItem.Services.Get<IUIElementAdapterFactoryCatalog>();
catalog.RegisterFactory(new ClickableTreeViewAdapterFactory());
// both main menus should have their items added to the root nodes collection
RootWorkItem.UIExtensionSites.RegisterSite(UIExtensionConstants.MAINMENU, Shell.MainNavigationTree);
// Load the menu structure from App.config
UIElementBuilder.LoadFromConfig(RootWorkItem, Shell.MainNavigationTree);
}
... {
base.AfterShellCreated();
IUIElementAdapterFactoryCatalog catalog = RootWorkItem.Services.Get<IUIElementAdapterFactoryCatalog>();
catalog.RegisterFactory(new ClickableTreeViewAdapterFactory());
// both main menus should have their items added to the root nodes collection
RootWorkItem.UIExtensionSites.RegisterSite(UIExtensionConstants.MAINMENU, Shell.MainNavigationTree);
// Load the menu structure from App.config
UIElementBuilder.LoadFromConfig(RootWorkItem, Shell.MainNavigationTree);
}