ListView.ItemContainerGenerator.ContainerFromItem(item)在20个项目后返回null

时间:2009-11-04 19:04:12

标签: wpf listview wpf-controls

首先,我想解释一下我要做的事情。我在ListView中有一个UserControl,其中DataTemplate被定义为资源。我想在DataTemplate中隐藏一个按钮。听起来很简单,但是......

我正在使用的代码是

<UserControl.Resources>
    <DataTemplate x:Key="Proyectos">
        <DockPanel Name="Panel"  Margin="0,0,0,0" MinWidth="1200" MaxWidth="1200">
            <Border Margin="0" BorderBrush="Bisque" BorderThickness="1" DockPanel.Dock="Left">

            <StackPanel Margin="0" Width="1135">
                <DockPanel>
                    <TextBlock  Text="{Binding titulo}" Name="titulo" FontWeight="Bold" FontSize="12" />
                </DockPanel>
                <DockPanel >
                    <TextBlock FontWeight="Bold" Text="Nº Ref. Fundacion: " DockPanel.Dock="Left" Margin="5,0,5,0" FontSize="11"/>
                    <TextBlock Name="txb_codproy"  Text="{Binding codproy}" FontSize="11"/>
                    <TextBlock FontWeight="Bold" Text="  Nº Ref. Proyecto: " FontSize="11"/>
                    <TextBlock Text="{Binding registro}" FontSize="11"/>
                    <TextBlock FontWeight="Bold" Text="  Estado: " FontSize="11"/>
                    <TextBlock Text="{Binding estados_proyecto.descripcion}" FontSize="11"/>
                </DockPanel>

                <DockPanel >
                    <TextBlock FontWeight="Bold" Text="Organismo " DockPanel.Dock="Left" Margin="5,0,5,0" FontSize="11"/>
                    <TextBlock Text="{Binding organismo.descripcion}" FontSize="11"/>
                </DockPanel>

            </StackPanel>

            </Border>
            <Border Margin="0" Width="Auto" BorderBrush="Transparent" BorderThickness="1" Background="White" HorizontalAlignment="Left">
                <Button Margin="0,0,0,0" VerticalAlignment="Center" HorizontalAlignment="Left" Name="btn_Eliminar" Click="btn_Eliminar_Click" Width="Auto" Height="25" Background="Transparent" BorderBrush="Transparent">
                    <Image Name="img_eliminar" Width="48" Source="imagenes/borrar.png" Height="19" />
                </Button>
            </Border>
        </DockPanel>
    </DataTemplate>
</UserControl.Resources>

<Grid Width="1300" Height="845.169">
    <ListView Margin="20,120.024,15.247,50" MouseDoubleClick="list_proyectos_MouseDoubleClick"  Name="list_proyectos" ItemsSource="{Binding}" ItemTemplate="{StaticResource Proyectos}">
    </ListView>
    <TextBox Margin="32,12,35,0" Name="txt_busqueda" TextChanged="textBox1_TextChanged" Background="AliceBlue" BorderBrush="Gray" Height="23" VerticalAlignment="Top" />
</Grid>


//////////////////////////////////////////////////////////

public Proyectos(IPrincipal identityA)
{
     list_proyectos.ItemsSource = ListaProyectos;
     list_proyectos.ItemContainerGenerator.StatusChanged += new EventHandler(ItemContainerGenerator_StatusChanged);
}

void ItemContainerGenerator_StatusChanged(object sender, EventArgs e)
{
    if (list_proyectos.ItemContainerGenerator.Status == System.Windows.Controls.Primitives.GeneratorStatus.ContainersGenerated)
    {
        list_proyectos.ItemContainerGenerator.StatusChanged -= ItemContainerGenerator_StatusChanged;
        Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Input, new VoidDelegate(DelayedAction));      
    }
}

delegate void VoidDelegate();

void DelayedAction()
{
    foreach (object item in list_proyectos.Items)
    {

        ListBoxItem lbitem = (ListBoxItem)list_proyectos.ItemContainerGenerator.ContainerFromItem(item);
        if (lbitem != null)
        {
            ContentPresenter contentPresenter = FindVisualChild<ContentPresenter>(lbitem);
            DataTemplate myDataTemplate = contentPresenter.ContentTemplate;
            Button b = (Button)lbitem.ContentTemplate.FindName("btn_Eliminar", contentPresenter);
            b.Visibility = Visibility.Hidden;
        }

    }
}

private T FindVisualChild<T>(DependencyObject obj)
    where T : DependencyObject
{
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
    {
        DependencyObject child = VisualTreeHelper.GetChild(obj, i);
        if (child != null && child is T)
            return (T)child;
    }

    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
    {
        DependencyObject child = VisualTreeHelper.GetChild(obj, i);
        T childOfChild = FindVisualChild<T>(child);
        if (childOfChild != null)
            return childOfChild;
    }

    return null;
}

我发现了两个问题,

  1. 此行(ListBoxItem)list_proyectos.ItemContainerGenerator.ContainerFromItem(item);在第16个项目后返回null。列表视图有1576项

  2. 当显示ListView并且前16个项目隐藏了按钮时,如果我向下滚动到最后,然后再次返回顶部,按钮再次可见。

1 个答案:

答案 0 :(得分:2)

ListView正在使用虚拟化,因此它不会为它知道不必显示的项目创建任何容器。这是一件“好事”,特别是考虑到你有1576件物品。

也许您可以解释为什么您希望能够获取不可见项目的容器,我们可以提供更好的建议。