【问题标题】:How to iterate controls in WPF如何在 WPF 中迭代控件
【发布时间】:2011-08-28 19:05:51
【问题描述】:

我有一个简单的 XAML 文件,其中有一个网格和文本框。但是当使用我的代码时,它没有通过迭代找到文本框。

VB.Net:

Dim ctl As FrameworkElement = Me.MainWindow

代码:

Dim ChildrenCount As Integer = VisualTreeHelper.GetChildrenCount(ctl)
'ChildrenCount is always zero
For i As Integer = 0 To ChildrenCount - 1
    Dim Child As FrameworkElement = VisualTreeHelper.GetChild(ctl, i)
    Call SetLanguageToControls(Keyword, cLanguage, Child)
Next

XAML:

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow"  Icon="/OUTPUT%20-%20Histogram;component/Sprectrum.ico">
    <Grid x:Name="LayoutRoot">
        <Grid x:Name="SpectrumContent" Margin="8" Height="120" Width="320">
            <Rectangle Grid.Row="0" Grid.Column="1" Opacity="0.5">
                <Rectangle.Fill>
                    <LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
                        <GradientStop Offset="0" Color="Black" />
                        <GradientStop Offset="1" Color="White" />
                    </LinearGradientBrush>
                </Rectangle.Fill>
            </Rectangle>
        <TextBlock x:Name="txtRedMin" Text="|Red:" Foreground="Red" FontWeight="Bold" />
        <TextBlock x:Name="txtRedMinValue" Text="000%" />
        </Grid>
    </Grid>
</Window>

编辑 问题解决了。我在管理插件中的语言时使用了代码。但是没有调用 MainWindow1.Loaded。如果未加载 Window,则此代码不起作用。如果加载了 Window,则此代码有效。

【问题讨论】:

  • 什么代码定义了ctl
  • 基础是主窗口。我想通过迭代接收所有控件的列表。问题不是如何迭代,而是如何接收frameworkelement的children列表。

标签: wpf vb.net xaml controls iterator


【解决方案1】:

您必须为每个子控件递归调用您的函数。也就是说,在以下行中,您将获得 ctl 的子代:

Dim Child As FrameworkElement = VisualTreeHelper.GetChild(ctl, i)

在此之后,您需要遍历 Child 的子级。

【讨论】:

  • 但 'i' 始终为 -1,因为 Count 为零
  • @goldengel 你什么时候打电话给这个?也许是在创建窗口的 UI 之前?
【解决方案2】:

VisualTreeHelper.GetChild 方法不递归。如果你想递归尝试使用Linq-To-VisualTree,例如

var textBlocks = ctl.Descendants<TextBlock>();

【讨论】:

  • 我知道它不是递归的。但是后裔在我的 ctl 类型(即 Frameworkelement)上不可用。你能给我建议吗?
  • 尝试点击答案中的链接:scottlogic.co.uk/blog/colin/2010/03/linq-to-visual-tree!!
  • 如何使用 LINQ 的重要文章。但解决方案不是通过过滤东西,而是在创建 UI 之前使用代码。感谢科林的帮助。
【解决方案3】:

这取决于您以ctl 传递的控制权

如果你通过窗口,你会得到边框

如果您通过 Grid(布局),您将获得子网格。

编辑

我刚刚注意到这一行

Dim ctl As FrameworkElement = Me.MainWindow

改成:

Dim ctl As FrameworkElement = Me

EDIT2

Private Sub Button1_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles Button1.Click
    Dim ctl As FrameworkElement
    ctl = LayoutRoot
    Dim ChildrenCount As Integer = VisualTreeHelper.GetChildrenCount(ctl)
    For i As Integer = 0 To ChildrenCount - 1
        Dim Child As FrameworkElement = VisualTreeHelper.GetChild(ctl, i)
        Debug.WriteLine(Child.ToString() + ": " +
                        VisualTreeHelper.GetChildrenCount(Child).ToString())
    Next
End Sub

【讨论】:

  • 也许我可以通过“If typeof ctl is Window Then”进行过滤。但是后来,怎么抓孩子呢?
  • 不过滤。将您正在寻找的孩子的父母传递给函数,并使用递归方法找到孩子的孩子。
  • 另外:我也发现了一些错误。请参阅我的答案中的编辑。
  • 感谢 Erno 的回复。如果我将 MainWindow 作为 Frameworkelement 发送到上面的类,我会收到 MainWindow 但“VisualTreeHelper.GetChildrenCount(ctl)”返回零。如果投射 MainWindow 并使用“ctl = MainWindow.Content”,则 ctl 是一个 Grid,但“VisualTreeHelper.GetChildrenCount(ctl)”为零且 .Children 为零(这是不寻常的)。我不明白为什么它是 0。
  • 解决了!在调用 MainWindow1.Loaded 之前,我已经要求提供控件。感谢您的大力帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-03
  • 1970-01-01
  • 1970-01-01
  • 2013-01-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多