Drag&Drop v Metru/Modern UI


Jak jednoduše na Drag & Drop akci v Metru, resp. Modern UI?

Celou akci ukážu na jednoduchém příkladu mezi prvky GridView a ListView. V podstatě stačí v prvním prvku nastavit property CanDragItems="True" a přidat událost DragItemsStarting, ve které se připraví data, resp. nějaký ukazatel pro následující obnovu, např. ID (pozn. oproti WPF nelze posílat celý object, proto právě ID). Na druhém prvku pak stačí nastavit property AllowDrop="True" a přidat událost Drop, ve které dojde právě k obnově ID a následné akci se záznamem podle logiky aplikace. V příkladu je použit pro stránku DataContext se 2 kolekcemi, kdy jedna je použita v GridView, druhá v ListView a samotný přenos probíhá mezi nimi podle ID vybraného záznamu (vhodné je založit nový projekt např. Windows Store –> Grid App).

Kód na pozadí stránky:


public sealed partial class ItemsPage
{
  public ItemsPage()
  {
    InitializeComponent();
    DataContext = new PersonViewModel
                    {
                      AllPersons = new ObservableCollection<PersonModel>
                                     {
                                       new PersonModel(1, "John", "Doe"),
                                       new PersonModel(2, "Jane", "Poe"),
                                       new PersonModel(3, "Robert", "Roe"),
                                       new PersonModel(4, "Mark", "Moe"),
                                     },
                      SelectedPersons = new ObservableCollection<PersonModel>(),
                    };
  }


  public new PersonViewModel DataContext
  {
    get { return base.DataContext as PersonViewModel; }
    set { base.DataContext = value; }
  }


  private void AllPersonsGridViewOnDragItemsStarting(object sender, DragItemsStartingEventArgs e)
  {
    PersonModel selectedPerson = e.Items.OfType<PersonModel>().FirstOrDefault();
    if (selectedPerson == null)
      return;
    e.Data.SetData(StandardDataFormats.Text, selectedPerson.Id.ToString());
  }

  private async void SelectedPersonsListViewOnDrop(object sender, DragEventArgs e)
  {
    DataPackageView dataPackageView = e.Data.GetView();
    if (dataPackageView == null)
      return;
    string selectedTextId = await dataPackageView.GetTextAsync();
    if (string.IsNullOrEmpty(selectedTextId))
      return;
    int selectedId;
    if (int.TryParse(selectedTextId, out selectedId))
    {
      PersonModel selectedPerson = DataContext.AllPersons.SingleOrDefault(x => x.Id == selectedId);
      if (selectedPerson == null)
        return;
      DataContext.SelectedPersons.Add(selectedPerson);
    }
  }
}

Zjednodušená definice layoutu stránky v XAMLu:


<common:LayoutAwarePage x:Class="DragDropSample.ItemsPage"
                        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                        xmlns:common="using:DragDropSample.Common">
  <Grid Style="{StaticResource LayoutRootStyle}">
    <Grid.RowDefinitions>
      <RowDefinition Height="*" />
      <RowDefinition Height="*" />
    </Grid.RowDefinitions>

    <GridView Grid.Row="0" Grid.Column="0" 
              Name="u_AllPersonsGridView"
              ItemsSource="{Binding AllPersons}"
              CanDragItems="True" 
              DragItemsStarting="AllPersonsGridViewOnDragItemsStarting" />

    <ListView Grid.Row="1" Grid.Column="0" 
              x:Name="u_SelectedPersonsListView"
              ItemsSource="{Binding SelectedPersons}"
              AllowDrop="True" 
              Drop="SelectedPersonsListViewOnDrop" />

  </Grid>
</common:LayoutAwarePage>

TIP1: pro možnost změny pořadí přetahováním v obou přehledových controlech stačí nastavit CanReorderItems="True" a zároveň musí být aktivní AllowDrop="True"…

TIP2: v případě použití systémových stylů (ve vzorových aplikacích Common/StandardStyles.xaml) je vhodné nastavit si vlastní výchozí styl pro GridView a ListView:


<Style TargetType="GridView/ListView">
  <Setter Property="Margin" Value="10" />
  <Setter Property="Padding" Value="10" />
  <Setter Property="Background" Value="{StaticResource ListBoxBackgroundThemeBrush}" />
  <Setter Property="BorderBrush" Value="{StaticResource ListBoxBorderThemeBrush}" />
  <Setter Property="BorderThickness" Value="{StaticResource ListBoxBorderThemeThickness}" />
</Style>

, , , , , ,

Komentáře jsou uzavřeny.