ItemsControl的行为

时间:2011-07-12 10:29:15

标签: wpf wpf-controls itemscontrol

我有一个包含多个UserControl的屏幕,但只有一个保持活动状态。其他UserControl未显示,但用户可以切换任何非活动的活动标志。其中一个UserControl包含ItemsControl。

我需要知道视图中的所有控件,包括ItemsControl生成的控件,在加载屏幕中活动的第一个UserControl后,最终初始化视图时。

对于ItemsControl,wpf没有实例化任何项目,直到它在包含UserControl的屏幕上绘制(所以我已经尝试过,直到Load事件被启动),所以我找不到包含的控件视图因为它不存在。

有没有办法改变这种行为?

我尝试将属性VirtualizingStackPanel.IsVirtualizing的值更改为false,以避免以前的行为,但没有成功。为了说明这一点,我写了这个视图示例:

<Window x:Class="ContenidoEnTabs.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
    <StackPanel x:Name="spContainer" Orientation="Vertical" VirtualizingStackPanel.IsVirtualizing="False">
        <Button Content="Push" Click="Button_Click" />
    </StackPanel>
</Window>

在用户按下按钮之前,此视图会创建第二个控件:

public partial class MainWindow : Window
{
    private NotPaintedOnInitUserControl controlExtra;

    public MainWindow()
    {
        InitializeComponent();
        controlExtra = new NotPaintedOnInitUserControl();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        spContainer.Children.Add(controlExtra);
    }
}

最初不可见的控件如下:

<UserControl x:Class="ContenidoEnTabs.NotPaintedOnInitUserControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d"
         d:DesignHeight="300" d:DesignWidth="300">
    <ItemsControl ItemsSource="{Binding MyCollection}" x:Name="itemsControlTarget" 
              VirtualizingStackPanel.IsVirtualizing="False">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <TextBox x:Name="aTextBox" Width="80" Initialized="ATextBox_Initialized" />
            </DataTemplate>
            </ItemsControl.ItemTemplate>
    </ItemsControl>
</UserControl>

并在CodeBehind中检测项目的创建时间

public partial class NotPaintedOnInitUserControl : UserControl
{
    public NotPaintedOnInitUserControl()
    {
        InitializeComponent();
        DataContext = new SimpleListDataContext();
    }

    private void ATextBox_Initialized(object sender, EventArgs e)
    {
    }
}

使用的DataContext:

public class SimpleListDataContext
{
    private List<string> _myCollection;
    public List<string> MyCollection
    {
        get { return _myCollection ?? (_myCollection = new List<string> { "one", "two" }); }
        set { _myCollection = value; }
    }
}

有什么想法吗?

提前致谢。

2 个答案:

答案 0 :(得分:0)

看看LogicalTreeHelper.GetChildren(myUiElement)

这会查看逻辑树而不是可视树,因此它会检查结构而无需加载控件以获取可视结构

在下面的控件中查找是contorl的名称,即myDatagrid

你也可以调整它以获得特定控制的所有孩子,即

FindChildInVisualTree(this, "mydatagrid"); // assumming this a UIElement (i.e. your in the code behind)

使用下面的方法找到控件,然后使用LogicalTreeHelper获取它的所有子项。

 public static UIElement FindChildInVisualTree(UIElement view, string controlToFind)
    {
        UIElement control = null;
        try
        {
            if (view != null)
            {
                if ((view as FrameworkElement).Name.ToUpper() == controlToFind.ToUpper())
                {
                    control = view;
                }
                else
                {
                    DependencyObject depObj = view as DependencyObject;
                    if (depObj != null)
                    {
                        foreach (var item in LogicalTreeHelper.GetChildren(depObj))
                        {
                            control = FindChildInVisualTree(item as UIElement, controlToFind);
                            if (control != null)
                            {
                                break;
                            }
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
            throw new ApplicationException("Error finding child control: " + controlToFind, ex);
        }
        return control;
    }

答案 1 :(得分:0)

如果希望WPF为不属于视图的控件生成树,可以通过强制布局运行来“水合”并布局控件。这样的事情应该有效:

public partial class MainWindow : Window
{
    private NotPaintedOnInitUserControl controlExtra;

    public MainWindow()
    {
        InitializeComponent();

        controlExtra = new NotPaintedOnInitUserControl();

        // Force the control to render, even though it's not on the screen yet.
        var size = new Size(this.Width, this.Height);
        var rect = new Rect(new Point(0,0), size);
        controlExtra.Measure(size);
        controlExtra.Arrange(rect);
        controlExtra.InvalidateVisual();
        controlExtra.UpdateLayout();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        spContainer.Children.Add(controlExtra);
    }
}

不确定这是不是你问的问题。如果没有,请澄清第2段。