我正在开发一款使用跨平台第三方布局引擎的应用,将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
答案 0 :(得分:0)
除了“System.InvalidCastException:指定的强制转换无效”之外,ListView
的该容器应该是ListViewItem
。
您应该可以设置CustomListViewCrash
的{{1}}继承来替换ItemsControl
。当ListView
类继承自CustomListViewCrash
时,ItemsControl
的容器不是CustomListViewCrash
。
如果您希望自己的班级继承自ListViewItem
,则应该能够将ListView
设置为Canvas
的{{1}}。我们应该可以删除Content
中的ListViewItem
方法。
例如:
base.PrepareContainerForItemOverride(element, item)