回答
這應該做的伎倆
public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}
foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}
那麼你枚舉控件像這樣
foreach (TextBlock tb in FindVisualChildren<TextBlock>(window))
{
// do something with tb here
}
完美,謝謝 – 2009-06-10 23:15:31
注意:如果你想讓這個工作,並發現你的窗口(例如)有0可視孩子,嘗試在Loaded事件處理程序中運行此方法。如果你在構造函數中運行它(甚至在InitializeComponent()之後),那麼可視化子項目不會被加載,並且它不起作用。 – 2009-08-28 15:02:52
使用幫助類VisualTreeHelper
或LogicalTreeHelper
,具體取決於您感興趣的tree。它們都提供獲取元素的子元素的方法(儘管語法稍有不同)。我經常使用這些類查找特定類型的第一次出現,但你可以很容易地修改它來尋找該類型的所有對象:
public static DependencyObject FindInVisualTreeDown(DependencyObject obj, Type type)
{
if (obj != null)
{
if (obj.GetType() == type)
{
return obj;
}
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject childReturn = FindInVisualTreeDown(VisualTreeHelper.GetChild(obj, i), type);
if (childReturn != null)
{
return childReturn;
}
}
}
return null;
}
+ 1解釋和帖子 但布賴斯卡爾發佈的功能,充分工作 謝謝 – 2009-06-10 23:18:25
這不能解決問題的問題,而且泛型類型的答案也更加清晰。將它與使用VisualTreeHelper.GetChildrenCount(obj)結合使用可以解決問題。 然而,將其視爲一種選擇很有用。 – 2015-10-07 12:38:33
,這是它如何工作的向上
private T FindParent<T>(DependencyObject item, Type StopAt) where T : class
{
if (item is T)
{
return item as T;
}
else
{
DependencyObject _parent = VisualTreeHelper.GetParent(item);
if (_parent == null)
{
return default(T);
}
else
{
Type _type = _parent.GetType();
if (StopAt != null)
{
if ((_type.IsSubclassOf(StopAt) == true) || (_type == StopAt))
{
return null;
}
}
if ((_type.IsSubclassOf(typeof(T)) == true) || (_type == typeof(T)))
{
return _parent as T;
}
else
{
return FindParent<T>(_parent, StopAt);
}
}
}
}
這是最簡單的方法:
IEnumerable<myType> collection = control.Children.OfType<myType>();
,其中控制是窗口的根元素。
請注意,使用VisualTreeHelper只適用於從Visual或Visual3D派生的控件。如果您還需要檢查其他元素(例如TextBlock,FlowDocument等),則使用VisualTreeHelper將引發異常。
下面是回落到如果有必要的邏輯樹的方法:
http://www.hardcodet.net/2009/06/finding-elements-in-wpf-tree-both-ways
獲取特定類型的所有孩子的列表,你可以使用:
private static IEnumerable<DependencyObject> FindInVisualTreeDown(DependencyObject obj, Type type)
{
if (obj != null)
{
if (obj.GetType() == type)
{
yield return obj;
}
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
foreach (var child in FindInVisualTreeDown(VisualTreeHelper.GetChild(obj, i), type))
{
if (child != null)
{
yield return child;
}
}
}
}
yield break;
}
我發現在上面的幾個示例中使用的行VisualTreeHelper.GetChildrenCount(depObj),不會返回GroupBoxes的非零計數,特別是在GroupBox包含Grid的情況下,並且Grid包含子元素。我相信這可能是因爲GroupBox不允許包含多個子元素,並且這個子元素存儲在它的Content屬性中。沒有GroupBox.Children類型的屬性。我相信,我不這樣做非常有效,但我修改在這條產業鏈的第一個「FindVisualChildren」舉例如下:
public IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
int depObjCount = VisualTreeHelper.GetChildrenCount(depObj);
for (int i = 0; i <depObjCount; i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}
if (child is GroupBox)
{
GroupBox gb = child as GroupBox;
Object gpchild = gb.Content;
if (gpchild is T)
{
yield return (T)child;
child = gpchild as T;
}
}
foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}
小改動,遞歸這樣你就可以例如找到的子標籤控件一個選項卡控件。
public static DependencyObject FindInVisualTreeDown(DependencyObject obj, Type type)
{
if (obj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
if (child.GetType() == type)
{
return child;
}
DependencyObject childReturn = FindInVisualTreeDown(child, type);
if (childReturn != null)
{
return childReturn;
}
}
}
return null;
}
我適應@Bryce卡勒的回答遵循@Mathias Lykkegaard洛倫岑的建議,並使用LogicalTreeHelper。
似乎工作沒關係。;!)
public static IEnumerable<T> FindLogicalChildren<T> (DependencyObject depObj) where T : DependencyObject {
if(depObj != null) {
foreach(object rawChild in LogicalTreeHelper.GetChildren(depObj)){
if(rawChild is DependencyObject) {
DependencyObject child = (DependencyObject)rawChild;
if(child is T) {
yield return (T)child;
}
foreach(T childOfChild in FindLogicalChildren<T>(child)) {
yield return childOfChild;
}
}
}
}
}
(它仍然不會檢查標籤控件或網格內GroupBoxes通過@Benjamin漿果& @大衛 - [R分別提及) (也跟着@ noonand的建議&被移去的冗餘子=空)
這裏是另一個,緊湊型,與泛型語法:
public static IEnumerable<T> FindLogicalChildren<T>(DependencyObject obj) where T : DependencyObject
{
if (obj != null) {
if (obj is T)
yield return obj as T;
foreach (DependencyObject child in LogicalTreeHelper.GetChildren(obj).OfType<DependencyObject>())
foreach (T c in FindLogicalChildren<T>(child))
yield return c;
}
}
我想添加評論,但我有低於50分,所以我只能用「答案」。 請注意,如果您使用「VisualTreeHelper」方法檢索XAML「TextBlock」對象,那麼它也將抓取XAML「Button」對象。如果通過寫入Textblock.Text參數重新初始化「TextBlock」對象,則不再能夠使用Button.Content參數更改Button文本。該按鈕將永久顯示來自Textblock.Text寫入操作寫入的文字(從當它被檢索 -
foreach (TextBlock tb in FindVisualChildren<TextBlock>(window))
{
// do something with tb here
tb.Text = ""; //this will overwrite Button.Content and render the
//Button.Content{set} permanently disabled.
}
要解決這個問題,你可以嘗試使用XAML「文本框」,並添加方法( 。或活動),以模仿XAMAL按鈕XAML「文本框」不爲「的TextBlock」的搜索聚集
我發現它更容易不可視樹助手:
foreach (UIElement element in MainWindow.Children) {
if (element is TextBox) {
if ((element as TextBox).Text != "")
{
//Do something
}
}
};
我的版本爲C++/CLI
template < class T, class U >
bool Isinst(U u)
{
return dynamic_cast<T>(u) != nullptr;
}
template <typename T>
T FindVisualChildByType(Windows::UI::Xaml::DependencyObject^ element, Platform::String^ name)
{
if (Isinst<T>(element) && dynamic_cast<Windows::UI::Xaml::FrameworkElement^>(element)->Name == name)
{
return dynamic_cast<T>(element);
}
int childcount = Windows::UI::Xaml::Media::VisualTreeHelper::GetChildrenCount(element);
for (int i = 0; i < childcount; ++i)
{
auto childElement = FindVisualChildByType<T>(Windows::UI::Xaml::Media::VisualTreeHelper::GetChild(element, i), name);
if (childElement != nullptr)
{
return childElement;
}
}
return nullptr;
};
由於某種原因,這裏發佈的答案都沒有幫助我獲得給定控件中包含的給定類型的所有控件在我的MainWindow中。 我需要在一個菜單中找到所有菜單項以迭代它們。他們並不都是菜單的直接後代,所以我設法只使用上面的任何代碼來收集他們的第一個lilne。 這個擴展方法是我爲這個問題的解決方案,任何人在這裏都會繼續閱讀。
public static void FindVisualChildren<T>(this ICollection<T> children, DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
var brethren = LogicalTreeHelper.GetChildren(depObj);
var brethrenOfType = LogicalTreeHelper.GetChildren(depObj).OfType<T>();
foreach (var childOfType in brethrenOfType)
{
children.Add(childOfType);
}
foreach (var rawChild in brethren)
{
if (rawChild is DependencyObject)
{
var child = rawChild as DependencyObject;
FindVisualChildren<T>(children, child);
}
}
}
}
希望它有幫助。
真的很好的答案。
VB.NET版本:
Public Shared Iterator Function FindVisualChildren(Of T As DependencyObject)(depObj As DependencyObject) As IEnumerable(Of T)
If depObj IsNot Nothing Then
For i As Integer = 0 To VisualTreeHelper.GetChildrenCount(depObj) - 1
Dim child As DependencyObject = VisualTreeHelper.GetChild(depObj, i)
If child IsNot Nothing AndAlso TypeOf child Is T Then
Yield DirectCast(child, T)
End If
For Each childOfChild As T In FindVisualChildren(Of T)(child)
Yield childOfChild
Next
Next
End If
End Function
使用(這禁用一個窗口中的所有文本框):
For Each tb As TextBox In FindVisualChildren(Of TextBox)(Me)
tb.IsEnabled = False
Next
- 1. 從WPF窗口訪問所有控件
- 2. 查找所有子控件WPF
- 3. 如何查找控件(WPF,C#)中的所有控件?
- 4. 找到所有現有的WPF控件
- 5. 清除wpf窗口中的所有用戶控件
- 6. 禁用WPF窗口中的所有輸入控件
- 7. WPF查找窗口實例
- 8. 從非窗口類訪問WPF控件
- 9. Silverlight:查找佈局中的所有類型控件
- 10. 在UIView中查找一個類型的所有控件
- 11. 找到ItemsControl中的所有控件 - WPF
- 12. 枚舉窗口內的所有控件
- 13. 在WPF窗口中禁用除一個子控件之外的所有控件
- 14. 查找WPF控件在視口中
- 15. 查找類實現的所有接口
- 16. Windows窗體查找所有活動窗體實例類型
- 17. 查找WPF列表框中的所有控件
- 18. 位置在窗口WPF控件的?
- 19. 超出WPF窗口的控件?
- 20. WPF窗口更改另一個窗口的控件的值
- 21. 檢索任何窗口的所有控件及其類型和值
- 22. 在子窗口頂部的WPF所有者窗口
- 23. WPF關閉主窗口的所有窗口
- 24. 如何將Win32窗口設置爲WPF窗口的所有者?
- 25. 查找所有父類型(基類和接口)
- 26. 查找同一類型的控件
- 27. 在WPF應用程序中查找所有打開的彈出窗口
- 28. 如何在wpf的瀏覽器控件中關閉查找窗口
- 29. WPF:從ListView查找父窗口ViewBase
- 30. 使用WITH RECURSIVE查找所有複合類型組件類型
雖然我們的話題,這也是相關的http://咕。 gl/i9RVx – 2012-08-14 14:01:22
我還寫了一篇關於以下主題的博客文章:[在運行時修改ControlTemplate](http://wpfexperiments.blogspot.com/2012/08/modifying-controltemplate-in-style-at.html) – 2012-08-31 12:52:21