gridviewuwpdrag-and-dropcontentpresenter

UWP - drag and drop with CanReorderItems= "true" in Gridview, app will crash that exception's message is "The parameter is incorrect"


I implemented drag and drop on GridView and used "Canreorder" property to change item's position. I encounter a crash if use a "ContentPresenter" on GridView when is dragging and dropping. The crash message is "The parameter is incorrect". I try to change the "ContentPresenter" to Image, it will work normal. But the control of "ContentPresenter" is needed for my application.

Could someone help to solve, please?

MainPage.xaml

<GridView
        Grid.Row="1"
        Margin="0,10,0,10"
        AllowDrop="True"
        CanDragItems="True"
        CanReorderItems="True"
        IsSwipeEnabled="True"
        ItemsSource="{x:Bind ViewModel.PreviewItems}">
        <GridView.ItemTemplate>
            <DataTemplate>
                <Grid
                    Width="340"
                    Height="240"
                    Padding="5,0,5,0"
                    BorderThickness="1">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="50" />
                        <RowDefinition Height="180" />
                    </Grid.RowDefinitions>

                    <ContentPresenter
                        Grid.Row="1"
                        HorizontalAlignment="Left"
                        VerticalAlignment="Top"
                        Content="{Binding ImageThumbnail}" />
                </Grid>

            </DataTemplate>
        </GridView.ItemTemplate>
        <GridView.ItemsPanel>
            <ItemsPanelTemplate x:Name="clu">
                <ItemsWrapGrid
                    MaximumRowsOrColumns="5"
                    Orientation="Horizontal" />
            </ItemsPanelTemplate>
        </GridView.ItemsPanel>
    </GridView>

MainViewModel.cs

public class MainViewModel : ObservableObject
{
    public ObservableCollection<PreviewItem> PreviewItems = new ObservableCollection<PreviewItem>();
    public MainViewModel()
    {
        for(int i = 0; i < 2; i++)
        {
            var item = new PreviewItem();
            item.ImageThumbnail = new Windows.UI.Xaml.Controls.Image();
            ImageSource result = new BitmapImage(new Uri("ms-appx:///Assets/Square150x150Logo.png"));
            item.ImageThumbnail.Source = result;

            PreviewItems.Add(item);
        }
    }
}

PreviewItem.cs

public class PreviewItem : ObservableObject
{
    private Image _imageThumbnail;
    public Image ImageThumbnail { get => _imageThumbnail; set => SetProperty(ref _imageThumbnail, value); }
  

    public PreviewItem()
    {
        
    }     
   
}

Here is my project and cord. https://github.com/houzhiwei/UWPProject

Thanks

Zack


Solution

  • It should be GridView default virtualization cause this behavior. The solutuion is that replace ItemsWrapGrid with WrapGrid (still use ContentPresenter as container), the following line could disable virtualization behavior and make drag and drop avaiable for ContentPresenter

    <ItemsPanelTemplate x:Name="clu">
        <WrapGrid Orientation="Horizontal"/>
    </ItemsPanelTemplate>
    

    I have to say it is bad proctice that generate image control in the model class. Even it could be rendered when gridview loading, but it will cause unexpected error when drag and drop.

    In general, we just make string soure propety in the model and bind it with image source property. For more infomation please refer to Data binding in depth

    Model

    public class PreviewItem : ObservableObject
    {
        private string _imageThumbnail;
    
        public string ImageThumbnail
        {
            get => _imageThumbnail;
    
            set => SetProperty(ref _imageThumbnail, value);
        }
    
    }
    

    ViewModel

    public class MainViewModel : ObservableObject
    {
        public ObservableCollection<PreviewItem> PreviewItems = new ObservableCollection<PreviewItem>();
        public MainViewModel()
        {
            for (int i = 0; i < 2; i++)
            {
                var item = new PreviewItem();
                item.ImageThumbnail = "ms-appx:///Assets/Square150x150Logo.png";      
                PreviewItems.Add(item);
            }
        }
    }
    

    Xaml Binding

    <ContentPresenter
        Grid.Row="1"
        HorizontalAlignment="Left"
        VerticalAlignment="Top">
        <Image Source="{Binding ImageThumbnail, Mode=OneWay}" />
    </ContentPresenter>
    

    Certainly, if you do regard it as an unexpect behavior, pleas feel free post this with windows feedback hub app.