Listview UWP应用程序中的GetContainerForItemOverride

Listview UWP应用程序中的GetContainerForItemOverride,listview,uwp,listviewitem,Listview,Uwp,Listviewitem,我正在开发一个应用程序,它使用一个跨平台的第三方布局引擎将UI元素放置在Visual Tree的特定坐标处(通过在画布中放置东西)。在我的场景中,我需要一个虚拟化的ListView,它的每一项都通过这个布局引擎 在我尝试从列表视图中删除项目之前,一切正常。我已经将问题缩小到这样一个事实:对于我的列表视图,当调用GetContainerForItemOverride()时,我将返回一个Canvas,而不是返回一个ListViewItem。但是我当然需要一个画布,这样布局引擎就可以把东西放在画布的特

我正在开发一个应用程序,它使用一个跨平台的第三方布局引擎将
UI元素
放置在
Visual Tree
的特定坐标处(通过在画布中放置东西)。在我的场景中,我需要一个虚拟化的
ListView
,它的每一项都通过这个布局引擎

在我尝试从列表视图中删除项目之前,一切正常。我已经将问题缩小到这样一个事实:对于我的列表视图,当调用GetContainerForItemOverride()时,我将返回一个
Canvas
,而不是返回一个
ListViewItem
。但是我当然需要一个
画布
,这样布局引擎就可以把东西放在
画布
的特定坐标上

我在下面创建了一个非常愚蠢的示例,它将重现我遇到的问题。基本上,当我试图通过调用
.RemoveAt()
.Remove()
来删除一个项目时,我会得到一个
无效的CastException
(顺便说一句,如果我在本例中使用
项目资源
,而不是直接添加到
.Items
),同样的问题也会发生

有人知道如何解决这个问题吗

这是密码

<Page x:Class="Sample.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:sample="using:Sample">

    <StackPanel>
        <sample:CustomListViewCrash x:Name="MyListViewCrash">
            <sample:CustomListViewCrash.ItemsPanel>
                <ItemsPanelTemplate>
                    <VirtualizingStackPanel Orientation="Vertical" />
                </ItemsPanelTemplate>
            </sample:CustomListViewCrash.ItemsPanel>
        </sample:CustomListViewCrash>

        <Button Content="Delete" Tapped="Delete_OnTapped" />
    </StackPanel>

</Page>
以下是有关异常的信息:

System.InvalidCastException occurred
  HResult=0x80004002
  Message=Specified cast is not valid.
  Source=System.Private.CoreLib
  StackTrace:
   at System.Runtime.InteropServices.WindowsRuntime.IVector`1.RemoveAt(UInt32 index)
   at System.Runtime.InteropServices.WindowsRuntime.VectorToListAdapter.RemoveAtHelper[T](IVector`1 _this, UInt32 index)
   at System.Runtime.InteropServices.WindowsRuntime.VectorToListAdapter.RemoveAt[T](Int32 index)
   at ReactiveDelete.MainPage.Delete_OnTapped(Object sender, TappedRoutedEventArgs e) in MainPage.xaml.cs:line 31
除了“System.InvalidCastException:指定的强制转换无效”之外,
ListView
的容器应该是
ListViewItem

您应该能够将
CustomListViewCrash
ItemsControl
继承设置为替换
ListView
。当
CustomListViewCrash
类从
ItemsControl
继承时,
CustomListViewCrash
的容器不是
ListViewItem

如果希望类继承自
列表视图
,则应该能够将
画布
设置为
列表视图项
内容。我们应该能够删除
PrepareContainerForItemOverride
中的
base.PrepareContainerForItemOverride(元素,项)
方法

例如:

public class CustomListViewCrash : ListView
{
    protected override DependencyObject GetContainerForItemOverride()
    {
        var canvas = new Canvas
        {
            Width = 100,
            Height = 50
        };
        canvas.Children.Add(new Button());
        var listViewItem = new ListViewItem();
        listViewItem.Content = canvas;
        return listViewItem;
    }

    protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
    {
        var listViewItem = (ListViewItem)element;
        var canvas = (Canvas)listViewItem.Content;
        var button = (Button)canvas.Children[0];
        button.Content = item;
    }
}

是的,照你说的做确实解决了不撞车的问题。不过,我发现您的方法还存在一些其他渲染问题(忽隐忽现)。但我认为这可能与我的应用程序有关,因此我将此标记为解决方案。谢谢
public class CustomListViewCrash : ListView
{
    protected override DependencyObject GetContainerForItemOverride()
    {
        var canvas = new Canvas
        {
            Width = 100,
            Height = 50
        };
        canvas.Children.Add(new Button());
        var listViewItem = new ListViewItem();
        listViewItem.Content = canvas;
        return listViewItem;
    }

    protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
    {
        var listViewItem = (ListViewItem)element;
        var canvas = (Canvas)listViewItem.Content;
        var button = (Button)canvas.Children[0];
        button.Content = item;
    }
}