UWP应用程序中的GetContainerForItemOverride

时间:2017-03-31 22:57:45

标签: listview uwp listviewitem

我正在开发一款使用跨平台第三方布局引擎的应用,将UI elements放置在特定坐标的Visual Tree中(通过在画布中放置内容)。在我的场景中,我需要虚拟化ListView,其中每个项目都通过此布局引擎。

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

我在下面创建了一个非常愚蠢的样本,它将重现我正在触及的问题。基本上当我尝试通过调用.RemoveAt().Remove()来删除项目时,我会得到一个InvalidCastException(顺便说一下,如果我在这个示例中使用ItemsSource,则会发生同样的问题而不是直接添加到.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>

背后的代码

public sealed partial class MainPage
{
    public MainPage()
    {
        InitializeComponent();
        MyListViewCrash.Items.Add("blah blah");
    }

    private void Delete_OnTapped(object sender, TappedRoutedEventArgs e)
    {
        if (MyListViewCrash.Items.Count > 0)
        {
            MyListViewCrash.Items.RemoveAt(0);
        }

    }
}

public class CustomListViewCrash : ListView
{
    protected override DependencyObject GetContainerForItemOverride()
    {
        var canvas = new Canvas
        {
            Width = 100,
            Height = 50
        };

        canvas.Children.Add(new Button());

        return canvas;
    }

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

        base.PrepareContainerForItemOverride(element, item);
    }
}

以下是有关异常的信息:

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

1 个答案:

答案 0 :(得分:0)

除了“System.InvalidCastException:指定的强制转换无效”之外,ListView的该容器应该是ListViewItem

您应该可以设置CustomListViewCrash的{​​{1}}继承来替换ItemsControl。当ListView类继承自CustomListViewCrash时,ItemsControl的容器不是CustomListViewCrash

如果您希望自己的班级继承自ListViewItem,则应该能够将ListView设置为Canvas的{​​{1}}。我们应该可以删除Content中的ListViewItem方法。

例如:

base.PrepareContainerForItemOverride(element, item)