1

Update: I received an answer from MS via support channels that it is currently impossible to support touch reordering when the ItemPanelTemplate is a VariableSizeWrapGrid - because it lacks the implementation of some of the interfaces required for that.

As a foreword (and to eliminate any misunderstanding), I do have the required functionality working with the mouse. All I need is to achieve the same functionality with the touch gestures.

Requirements: 1. Display in a horizontally scrollable container a set of items, each of which may be of either half height or full height. It should be possible to rearrange them by dragging and dropping at a new position. 2. Give the user a way to deselect a previously selected item (to the same effect as right-clicking with the mouse does).

My current code:

XAML (slightly simplified for clarity)

    <ScrollViewer HorizontalAlignment="Stretch" 
                  HorizontalScrollBarVisibility="Auto" 
                  VerticalScrollBarVisibility="Hidden">
        <StackPanel Orientation="Horizontal" Height="600" 
                    ScrollViewer.VerticalScrollMode="Disabled">
            <controls:MyGridView ScrollViewer.VerticalScrollMode="Disabled"
                                 ItemsSource="{Binding Items}" 
                                 SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
                                 SelectionMode="Single" 
                                 IsSwipeEnabled="True" 
                                 CanDragItems="True" 
                                 CanReorderItems="True" 
                                 AllowDrop="True" 
                                 IsItemClickEnabled="False"
                                 Height="600">
                <GridView.ItemTemplate>
                    <DataTemplate>
                        <Grid>
                            <ContentControl Content="{Binding}" 
                                            ContentTemplateSelector="{StaticResource ItemTemplateSelector}"/>
                        </Grid>
                    </DataTemplate>
                </GridView.ItemTemplate>

                <GridView.ItemsPanel>
                    <ItemsPanelTemplate>
                        <VariableSizedWrapGrid ItemHeight="300" 
                                               ItemWidth="300" 
                                               Orientation="Vertical"/>
                    </ItemsPanelTemplate>
                </GridView.ItemsPanel>

                <GridView.ItemContainerStyle>
                    <Style TargetType="GridViewItem">
                        <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
                        <Setter Property="VerticalContentAlignment" Value="Stretch"/>
                    </Style>
                </GridView.ItemContainerStyle>
            </controls:DashletsGridView>
        </StackPanel>
    </ScrollViewer>

MyGridView class here is an extension of GridViewEx that is a part of this sample. The only addition it has to its base class is:

    protected override void PrepareContainerForItemOverride(Windows.UI.Xaml.DependencyObject element, object item)
    {
        try
        {
            Item d = item as Item;
            if (d != null)
            {
                element.SetValue(VariableSizedWrapGrid.RowSpanProperty, d.Size == PossibleSizes.Half ? 1 : 2);
            }
        }
        catch
        {
            element.SetValue(VariableSizedWrapGrid.RowSpanProperty, 2);
        }
        finally
        {
            base.PrepareContainerForItemOverride(element, item);
        }
    }

I have tried a wide variety of layout control combinations (such as eliminating the outer ScrollViewer, or StackPanel, or replacing it with a grid), but none of those supported proper horizontal scrolling or item sizing. Switching the GridView.ItemsPanel from VariableSizedWrapGrid to just WrapGrid did not help either.

Please note the combination of flags: IsSwipeEnabled="True" CanDragItems="True" CanReorderItems="True" AllowDrop="True" IsItemClickEnabled="False". This is what's working with the mouse d&d, but still no luck with the touch d&d or deselection.

Alex
  • 441
  • 5
  • 19
  • Have you see this ? http://www.codeproject.com/Articles/536519/Extending-GridView-with-Drag-and-Drop-for-Grouping – Farhan Ghumra May 31 '13 at 16:18
  • Xyroid: this is the same article I reference as the origin of the GridViewEx. Unfortunately, as similar as its functionality is, it is not exactly the same, and I wasn't able to figure out which part of the delta causes my solution to not respond to gestures :-( – Alex May 31 '13 at 16:21
  • I had a somewhat similar problem discussed here: http://social.msdn.microsoft.com/Forums/en-US/winappswithcsharp/thread/b04df2e0-357d-4533-972a-80a5bbcfc4c5. In my case, setting the HorizontalScrollMode property to Disabled made swiping not work. Finally I was forced to enable HorizontalScrollMode on my GridView. (This might not be related to your case.) – Mark Vincze Jun 04 '13 at 18:12
  • It is polite to mark the correct answer. – Jerry Nixon Jun 20 '13 at 15:25
  • Jerry, I'm a big fan of your blog, and have nothing but deep respect for you. But your answer was... How should I put it... To a different question. Of course my item is bound to an ObservableCollection. And I don't believe I've mentioned CollectionViewSourse. So, while your answer is nominally correct, it is not an answer to *my* question. So, with all the due respect, I am not going to mark your answer as correct. Because it isn't, not because I am impolite :-) – Alex Jun 20 '13 at 16:06

1 Answers1

0

You cannot reorder a GridView unless the ItemsSource is bound to an ObservableCollection and CanReorderItems, CanDragItems, and AllowDrop are set to true. It is not necessary to use a CollectionViewSource to enable reordering in your gridview. In fact, a collectionviewsource is often used for grouping a gridview and reordering is not possible when data is grouped.

Anyway, your XAML would look like this:

<Grid Background="Black">
    <Grid.DataContext>
        <local:MyModel/>
    </Grid.DataContext>
    <GridView CanReorderItems="True" CanDragItems="True" AllowDrop="True"
              ItemsSource="{Binding Items}">
    </GridView>
</Grid>

Although any enumerable can be bound to the ItemsSource of a GridView it is only an ObservableCollection that enables reorder. Yes, you can use a custom type that implements reorder, but why mess with that when ObservableCollection does it for you?

This is a snippet from my answer here.

Don't get discouraged. It's easier than it looks.

Best of luck!

Community
  • 1
  • 1
Jerry Nixon
  • 31,313
  • 14
  • 117
  • 233