2012年2月19日 星期日

WPF體系的邏輯樹/視覺樹常用操作

 

適用WPF,部分適用於Silverlight。

using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Media;

namespace OrcaPlayer.Common
{
public class TreeHelper
{
private static object _SyncRoot = new object();

<summary>
IsolatedStorageHelper Static Constructor.
</
summary>
static TreeHelper()
{

}

private static TreeHelper _instance = null;
<summary>
</
summary>
public static TreeHelper Instance
{
get
{
lock (_SyncRoot)
{
if (_instance == null)
{
_instance = new TreeHelper();
}
return _instance;
}
}
}


public DependencyObject FindVirtualTreeRoot(DependencyObject initial)
{
DependencyObject current = initial;
DependencyObject result = initial;

while (current != null)
{
result = current;

if (current is Visual || current is Visual3D)
{
current = VisualTreeHelper.GetParent(current);
}
else
{
current = LogicalTreeHelper.GetParent(current);
}
}

return result;
}

public DependencyObject FindLogicalTreeRoot(DependencyObject initial)
{
DependencyObject current = initial;
DependencyObject result = initial;

while (current != null)
{
result = current;
current = LogicalTreeHelper.GetParent(current);
}

return result;
}

//using System.Windows;
public DependencyObject GetTemplateParent(DependencyObject depObj)
{
FrameworkElement fe = depObj as FrameworkElement;
FrameworkContentElement fce = depObj as FrameworkContentElement;

DependencyObject result;

if (fe != null)
{
result = fe.TemplatedParent;
}
else if (fce != null)
{
result = fce.TemplatedParent;
}
else
{
result = null;
}

return result;
}

//最近邏輯樹上的父節點
public DependencyObject FindClosestLogicalAncestor(DependencyObject initial)
{
DependencyObject current = initial;
DependencyObject result = initial;

while (current != null)
{
DependencyObject logicalParent = LogicalTreeHelper.GetParent(current);

if (logicalParent != null)
{
result = current;
break;
}

current = VisualTreeHelper.GetParent(current);
}

return result;
}

//最近視覺樹上的父節點
public DependencyObject FindClosestVisualAncestor(DependencyObject initial)
{
if (initial is Visual || initial is Visual3D)
{
return initial;
}

DependencyObject current = initial;
DependencyObject result = initial;

while (current != null)
{
result = current;

if (current is Visual || current is Visual3D)
{
result = current;
break;
}
else
{
current = LogicalTreeHelper.GetParent(current);
}
}

return result;
}

//顯示邏輯樹
//private TreeView tree = new TreeView();
public void PopulateLogicalTree(TreeViewItem parentItem, object currentElement)
{
TreeViewItem item = new TreeViewItem();

item.IsExpanded = true;

if (parentItem == null)
{
item.Header = currentElement.GetType().Name;
tree.Items.Add(item);
}
else
{
item.Header = currentElement.GetType().Name;
parentItem.Items.Add(item);
}

DependencyObject curObject = currentElement as DependencyObject;

if (curObject != null)
{
foreach (object chElement in LogicalTreeHelper.GetChildren(curObject))
{
PopulateLogicalTree(item, chElement);
}
}
}

//顯示視覺樹
//private TreeView tree = new TreeView();
public void PopulateVisualTree(TreeViewItem parentItem, DependencyObject currentElement)
{
TreeViewItem item = new TreeViewItem();

item.IsExpanded = true;

if (parentItem == null)
{
item.Header = currentElement.GetType().Name;
tree.Items.Add(item);
}
else
{
item.Header = currentElement.GetType().Name;
parentItem.Items.Add(item);
}

int visualChildrenCount = VisualTreeHelper.GetChildrenCount(currentElement);

for (int i = 0; i < visualChildrenCount; i++)
{
DependencyObject visualChild = VisualTreeHelper.GetChild(currentElement, i);
PopulateVisualTree(item, visualChild);
}
}

//ex: CheckBox chb = this.FindFirstVisualChild<CheckBox>(listViewItem)
public T FindFirstVisualChild<T>(DependencyObject parentElement) where T : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parentElement); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(parentElement, i);

if (child != null && child is T)
{
return child as T;
}
else
{
T result = FindFirstVisualChild<T>(child);

if (result != null)
{
return result;
}
}
}

return null;
}

//TextBlock textBlock = GetFrameworkElementByName<TextBlock>(rowPresenter, "textBlock");
public T GetFrameworkElementByName<T>(FrameworkElement parentElement, String name) where T : FrameworkElement
{
FrameworkElement child = null;

for (Int32 i = 0; i < VisualTreeHelper.GetChildrenCount(parentElement); i++)
{
Debug.WriteLine("TreeHelper.cs::GetFrameworkElementByName " + parentElement.GetType().ToString() + " " + i.ToString());
child = VisualTreeHelper.GetChild(parentElement, i) as FrameworkElement;

if (child != null && child.Name == name && child.GetType() == typeof(T))
{
break;
}

else if (child != null)
{
child = GetFrameworkElementByName<T>(child, name);
}
}

return child as T;
}

//ContentPresenter cp = VisualTreeHelper.GetChild(CInfoContentControl, 0) as ContentPresenter;
//Button DownloadButton = TreeHelper.Instance.FindVisualChild<Button>(cp, 0, 3, 0, 0, 1) as Button;
//第二參數為第一參數下的的每一層子元素(子元素從0起算)
public T FindVisualChild<T>(DependencyObject parentElement, params int[] list) where T : DependencyObject
{
DependencyObject child = null;
for (int i = 0; i < list.Length; i++)
{
Debug.WriteLine("i=[" + i.ToString() + "] list[i]=[" + list[i].ToString() + "]");

if (i == 0)
{
if (VisualTreeHelper.GetChildrenCount(parentElement) > 0)
{
child = VisualTreeHelper.GetChild(parentElement, list[0]);
Debug.WriteLine("子元素型別=[" + child.GetType().ToString() + "]");
}
else
{
Debug.WriteLine(i.ToString() + " 子元素個數=[" + VisualTreeHelper.GetChildrenCount(parentElement).ToString() + "]");
}
}
else
{
if (VisualTreeHelper.GetChildrenCount(child) > 0)
{
child = VisualTreeHelper.GetChild(child, list[i]);
Debug.WriteLine("子元素型別=[" + child.GetType().ToString() + "]");
}
else
{
Debug.WriteLine(i.ToString() + " 子元素個數=[" + VisualTreeHelper.GetChildrenCount(child).ToString() + "]");
}
}
}

if (child != null && child is T)
{
return child as T;
}
else
{
return null;
}
}


public static T GetValue<T>(this BindingExpression expression, object dataItem)
{
if (expression == null || dataItem == null)
{
return default(T);
}

string bindingPath = expression.ParentBinding.Path.Path;
string[] properties = bindingPath.Split('.');

object currentObject = dataItem;
Type currentType = null;

for (int i = 0; i < properties.Length; i++)
{
currentType = currentObject.GetType();
PropertyInfo property = currentType.GetProperty(properties[i]);
if (property == null)
{
currentObject = null;
break;
}
currentObject = property.GetValue(currentObject, null);
if (currentObject == null)
{
break;
}
}

return (T)currentObject;
}

}
}


參考資料: