2017-03-31 6 views
0

クロスプラットフォームのサードパーティのレイアウトエンジンを使用して、特定の座標でVisual TreeUI elementsを配置する(キャンバスに物を入れることによって)アプリを開発しています。私のシナリオでは、仮想化が必要ですListViewすべての項目がこのレイアウトエンジンを通過する場所。UConPアプリケーションのGetContainerForItemOverride

リストビューからアイテムを削除しようとするまでは問題ありません。私は、ListViewItemを返すのではなく、GetContainerForItemOverride()が呼び出されたときに私のリストビューでCanvasを返すという事実に、問題を絞り込んだ。しかし、もちろんCanvasが必要なので、レイアウトエンジンはCanvasの特定の座標に物を入れることができます。

私が打つ問題を再現する非常にばかげたサンプルを作成しました。基本的に.RemoveAt()または.Remove()を呼び出してアイテムを削除しようとすると、.Itemsに直接追加するのではなく、ItemsSourceを使用している場合に同じ問題が発生します。

誰でもこの問題の解決方法を知っていますか?

は、ここでは、コード

<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

System.InvalidCastExceptionの「の例外から:指定されましたキャストが有効ではありません "、ListViewのコンテナはListViewItem

CustomListViewCrashItemsControlから継承し、ListViewの代わりに設定する必要があります。 CustomListViewCrashクラスがItemsControlから継承する場合、CustomListViewCrashのコンテナはListViewItemではありません。

あなたのクラスがListViewから継承したい場合は、ListViewItemContentCanvasを設定することができるはずです。 PrepareContainerForItemOverridebase.PrepareContainerForItemOverride(element, 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; 
    } 
} 
+0

はいあなたがクラッシュを打つていないという問題を解決しないと述べた何をやって。私はあなたのアプローチでいくつかの他のレンダリングの問題(ちらつき)を見ている。しかし、それは私のアプリに関連するかもしれないと思うので、私はこれを解決策としてマークしています。ありがとう。 –

関連する問題