gpt4 book ai didi

silverlight - 递归silverlight元素查找器扩展方法

转载 作者:行者123 更新时间:2023-12-04 06:59:17 26 4
gpt4 key购买 nike

我需要一个扩展方法来遍历 Silverlight 页面上的所有文本框。假设我总是使用网格布局,那么我有:

public static IEnumerable<UIElement> Traverse(this UIElementCollection source, Func<Grid, UIElementCollection> fnRecurse)
{
foreach (UIElement item in source)
{
yield return item;
var g = source.OfType<Grid>();
foreach (Grid itemsub in g)
{
var t = fnRecurse(itemsub);
t.Traverse(fnRecurse);
yield return itemsub;

};
}

}

现在,我可以这样称呼它:
baseLayout.Children.Traverse(x =>  x.Children ).OfType<TextBox>().ForEach(
w =>
{
//Text Box Extension Method, clears the text
w.reset();
});

这永远不会触发。我相信是 OfType 无法区分 UI 元素。

我该怎么做?我想展平视觉树然后循环。不仅仅是文本框,而是获得我想要的一切。我是在错误的地方还是过于频繁地让步?

编辑:

当前代码
public static IEnumerable<UIElement> Traverse(this UIElementCollection source, Func<Grid, UIElementCollection> fnRecurse)
{

foreach (UIElement item in source)
{
source.OfType<Grid>().Select(x => x.Children).ForEach(v => Traverse(v, fnRecurse));
yield return item;
}

}

网格是
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="42"/>
<RowDefinition Height="42"/>
<RowDefinition Height="45"/>
<RowDefinition Height="43"/>
<RowDefinition Height="47"/>
<RowDefinition Height="46"/>
<RowDefinition/>
<RowDefinition Height="67"/>
</Grid.RowDefinitions>
<Button x:Name="saveAddressButton" Height="24" HorizontalAlignment="Left" Margin="8,0,0,8" VerticalAlignment="Bottom" Width="135" Content="Save and Add More" Click="saveClick" Style="{StaticResource SaveButton}" Foreground="White" Grid.Row="7"/>
<Button x:Name="saveAddressButton_Copy" Height="24" HorizontalAlignment="Right" Margin="0,0,8,8" VerticalAlignment="Bottom" Width="81" Content="Clear" Click="clearClick" Style="{StaticResource SaveButton}" Foreground="White" Grid.Row="7"/>
<Grid Height="30" VerticalAlignment="Top" Margin="8,9,8,0">
<TextBlock Margin="8,0,0,0" Text="AddressLine1" FontSize="16" Foreground="White" HorizontalAlignment="Left" Width="121"/>
<TextBox x:Name="inputAddressLine1" TextWrapping="Wrap" Margin="218,0,0,0"/>
</Grid>
<Grid Height="30" Margin="8,8,8,0" VerticalAlignment="Top" Grid.Row="2">
<TextBlock Margin="8,0,0,0" Text="AddressLine2" FontSize="16" Foreground="White" HorizontalAlignment="Left" Width="146"/>
<TextBox x:Name="inputAddressLine2" TextWrapping="Wrap" Margin="219,0,0,0"/>
</Grid>
<Grid Height="30" Margin="8,0,8,7" VerticalAlignment="Bottom" Grid.Row="1">
<TextBlock Margin="8,0,0,0" Text="Post Code" FontSize="16" Foreground="White" HorizontalAlignment="Left" Width="107"/>
<TextBox x:Name="inputPostCode" TextWrapping="Wrap" Margin="219,0,0,0"/>
</Grid>
<Grid Height="30" VerticalAlignment="Bottom" Margin="8,0,8,9" Grid.Row="4">
<TextBox x:Name="inputCounty" TextWrapping="Wrap" Margin="220,0,0,0"/>
<TextBlock Margin="8,0,0,0" Text="County" FontSize="16" Foreground="White" HorizontalAlignment="Left" Width="155"/>
</Grid>
<Grid Margin="8,8,8,5" Grid.Row="3">
<TextBox x:Name="inputTown" TextWrapping="Wrap" Margin="219,0,0,0"/>
<TextBlock Margin="8,0,0,0" Text="AddressLine2" FontSize="16" Foreground="White" HorizontalAlignment="Left" Width="165"/>
</Grid>
<Grid Margin="8" Grid.Row="5">
<TextBlock Text="Number" FontSize="16" Foreground="White" Margin="8,0,0,0" HorizontalAlignment="Left" Width="178"/>
<TextBox x:Name="inputNumber" TextWrapping="Wrap" Margin="220,0,0,0"/>
</Grid>
</Grid>

仍然只是让这个深入一层,返回 6 个网格和一个按钮!

我目前的遍历功能是:
public static IEnumerable<UIElement> Traverse(this UIElementCollection source)
{
source.OfType<Grid>().SelectMany(v => Traverse(v.Children));
//This is the top level.
foreach (UIElement item in source)
{
yield return item;
}
}

这只是知道我们正在处理网格,所以不需要第二个参数。我只是从迭代器框让步,而不是从应该用子网格回调到 Traverse 函数的第一行。

最佳答案

这是我用来提供这种东西的功能:-

    public static IEnumerable<DependencyObject> Descendents(this DependencyObject root)
{
int count = VisualTreeHelper.GetChildrenCount(root);
for (int i = 0; i < count; i++)
{
var child = VisualTreeHelper.GetChild(root, i);
yield return child;
foreach (var descendent in Descendents(child))
yield return descendent;
}
}

使用该扩展方法,您的代码将变为:-
 foreach(var txt in baseLayout.Descendents().OfType<TextBox>())
{
txt.reset();
}

请注意,避免使用“foreach”扩展方法是一种选择。我不喜欢 LINQEsq 扩展方法实际上改变或为他的应用程序做任何事情的想法。我更喜欢使用合适的 foreach然后实际对查询结果进行操作。

编辑 对于“扩展方法瘾君子”(如果您明智,您 不会 这样做):-
 public static IEnumerable<T> ForEach(this IEnumerable<T> items, Action<T> fn)
{
foreach (T item in items)
fn(item);
}

编辑 你的代码有什么问题。

好吧,主要是您的 Traverse 方法深处的这一行是您问题的主要原因:-
 t.Traverse(fnRecurse);

它返回一个 IEnumerable<UIElement>但是你什么都不用做,甚至不将结果存储在变量中。

还有这一行:-
var g = source.OfType<Grid>();

对于找到的每个 UIElement,将导致枚举找到的每个网格。因此,例如,如果源包含一个文本框和 2 个网格,则上面的行会被调用 3 次。两个网格都将穿过内部 foreach两次。

还有这一行:-
yield return itemsub;

好 itemsub 始终是 Grid并且会被后面的 TypeOf<TextBox> 过滤掉.

因此,此代码将返回的唯一文本框是在初始 UIElementCollection 中找到的任何文本框。 .

关于silverlight - 递归silverlight元素查找器扩展方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2140042/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com