如何在 C# WPF 中访问具有给定标记的所有 XAML 元素?
How do I access all XAML elements with a given tag in C# WPF?
在我的 XAML 中,我有以下结构中的各种错误消息:
<Border CornerRadius="3" Background="#FFF3C7C7" Margin="6" Visibility="Collapsed" Name="quick_error" Tag="err_box">
<TextBlock Name="err_msg" Foreground="#FFFD3434" TextWrapping="Wrap" Margin="6" ></TextBlock>
</Border>
除名称外,块将完全相同。
我正在尝试编写代码以立即关闭所有可见错误。为此,我使用递归函数遍历我的主容器的所有子元素,然后从那里查找任何子元素,并在它们上面查找 iterate/recurse (因为错误可以在任何深度和内部父容器的任意组合)。
private void ShowError(string errName,string errMsg)
{
Border errBox = (Border) mainApp.FindName(errName);
errBox.Visibility = Visibility.Visible;
TextBlock msg = (TextBlock) errBox.FindName("err_msg");
msg.Text = errMsg;
}
private void RecurseChildren(DependencyObject child)
{
if (child is Border)
{
Border temp = (Border)child;
if (temp.Tag == "err_box")
ShowError("quick_error", temp.Name);
}
for(var i = 0; i < VisualTreeHelper.GetChildrenCount(child); i++)
{
RecurseChildren(VisualTreeHelper.GetChild(child, i));
}
}
private void TestRecurse()
{
foreach (UIElement child in mainApp.Children)
{
RecurseChildren(child);
}
}
现在,上面的代码被设计为在一个错误框(名为“quick_error”)中显示一条消息作为测试。我试图让它显示它找到的边界的名称(我知道这些名称将被找到的下一个边界覆盖,但这足以证明它正在工作所以没关系)。
但由于某种原因,没有任何显示。作为测试,我删除了 if 语句,但错误框中显示的值是“border”,这不是我 XAML 中任何边框的名称。我有两个边框值,一个名为“temp”,另一个名为“quick_error”。
我尝试只显示标记名,但如果我这样做...
ShowError("quick_error", (string)temp.Tag);
...它只是空白。为了测试,我为我的另一个边框分配了一个标签,所以它们都有一个标签,但它仍然是空白的。所以标签和名称都没有返回预期值。我做错了什么?
我找到了一个答案,该答案仅取决于属于同一类型控件的标签(在我的情况下很好,因为我使用 Border 作为错误消息):
public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj == null) yield return (T)Enumerable.Empty<T>();
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject ithChild = VisualTreeHelper.GetChild(depObj, i);
if (ithChild == null) continue;
if (ithChild is T t) yield return t;
foreach (T childOfChild in FindVisualChildren<T>(ithChild)) yield return childOfChild;
}
}
private void HideErrors()
{
foreach (Border temp in FindVisualChildren<Border>(mainApp))
{
if (temp.Tag != null && temp.Tag.ToString() == "err_box")
{
temp.Visibility = Visibility.Collapsed;
}
}
}
Findvisualchildren 是我在这个问题中找到的函数:Find all controls in WPF Window by type
在我的 XAML 中,我有以下结构中的各种错误消息:
<Border CornerRadius="3" Background="#FFF3C7C7" Margin="6" Visibility="Collapsed" Name="quick_error" Tag="err_box">
<TextBlock Name="err_msg" Foreground="#FFFD3434" TextWrapping="Wrap" Margin="6" ></TextBlock>
</Border>
除名称外,块将完全相同。
我正在尝试编写代码以立即关闭所有可见错误。为此,我使用递归函数遍历我的主容器的所有子元素,然后从那里查找任何子元素,并在它们上面查找 iterate/recurse (因为错误可以在任何深度和内部父容器的任意组合)。
private void ShowError(string errName,string errMsg)
{
Border errBox = (Border) mainApp.FindName(errName);
errBox.Visibility = Visibility.Visible;
TextBlock msg = (TextBlock) errBox.FindName("err_msg");
msg.Text = errMsg;
}
private void RecurseChildren(DependencyObject child)
{
if (child is Border)
{
Border temp = (Border)child;
if (temp.Tag == "err_box")
ShowError("quick_error", temp.Name);
}
for(var i = 0; i < VisualTreeHelper.GetChildrenCount(child); i++)
{
RecurseChildren(VisualTreeHelper.GetChild(child, i));
}
}
private void TestRecurse()
{
foreach (UIElement child in mainApp.Children)
{
RecurseChildren(child);
}
}
现在,上面的代码被设计为在一个错误框(名为“quick_error”)中显示一条消息作为测试。我试图让它显示它找到的边界的名称(我知道这些名称将被找到的下一个边界覆盖,但这足以证明它正在工作所以没关系)。
但由于某种原因,没有任何显示。作为测试,我删除了 if 语句,但错误框中显示的值是“border”,这不是我 XAML 中任何边框的名称。我有两个边框值,一个名为“temp”,另一个名为“quick_error”。
我尝试只显示标记名,但如果我这样做...
ShowError("quick_error", (string)temp.Tag);
...它只是空白。为了测试,我为我的另一个边框分配了一个标签,所以它们都有一个标签,但它仍然是空白的。所以标签和名称都没有返回预期值。我做错了什么?
我找到了一个答案,该答案仅取决于属于同一类型控件的标签(在我的情况下很好,因为我使用 Border 作为错误消息):
public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj == null) yield return (T)Enumerable.Empty<T>();
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject ithChild = VisualTreeHelper.GetChild(depObj, i);
if (ithChild == null) continue;
if (ithChild is T t) yield return t;
foreach (T childOfChild in FindVisualChildren<T>(ithChild)) yield return childOfChild;
}
}
private void HideErrors()
{
foreach (Border temp in FindVisualChildren<Border>(mainApp))
{
if (temp.Tag != null && temp.Tag.ToString() == "err_box")
{
temp.Visibility = Visibility.Collapsed;
}
}
}
Findvisualchildren 是我在这个问题中找到的函数:Find all controls in WPF Window by type