none
WPF - Ereignis nach Drop? RRS feed

  • Frage

  • Hallo,

    ich habe in WPF eine datengebundene Listbox, in der ich die Elemente per Drag & Drop neu anordnen kann. Das funktioniert auch soweit. Nun möchte ich, dass das Element an seiner neuen Stelle (also nach einem Drop) selektiert wird. Gibt es in WPF ein Ereignis für die ListBox, dass nach einem Drop ausgeführt wird? Also wenn die Elemente schon neu angeordnet sind?

    Montag, 5. März 2018 17:50

Antworten

  • Hi,
    Du kannst einfach SelectedIndex auf die Position des eingefügten Objektes setzen, z.B. so:

    XAML:

    <Window x:Class="WpfApp1CS.Window36"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApp1CS"
            xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
            mc:Ignorable="d"
            Title="Window36" Height="300" Width="300">
      <Window.Resources>
        <local:Window36VM x:Key="vm"/>
      </Window.Resources>
      <Grid DataContext="{StaticResource vm}">
        <ListBox ItemsSource="{Binding Liste}" AllowDrop="True" DisplayMemberPath="Info">
          <i:Interaction.Behaviors>
            <local:Window36Behavior/>
          </i:Interaction.Behaviors>
        </ListBox>
      </Grid>
    </Window>

    Dazu der ViewModel und die anderen Klassen:

    using System;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Input;
    using System.Windows.Interactivity;
    
    namespace WpfApp1CS
    {
      public class Window36VM
      {
        CollectionViewSource cvs = new CollectionViewSource();
        public ObservableCollection<Window36Data> Collection = new ObservableCollection<Window36Data>();
        public ICollectionView Liste
        {
          get
          {
            if (cvs.Source == null)
            {
              for (int i = 1; i < 20; i++) Collection.Add(new Window36Data() { Info = $"Zeile {i}" });
              cvs.Source = Collection;
            }
            return cvs.View;
          }
        }
      }
    
      public class Window36Data
      {
        public Guid ID { get; } = Guid.NewGuid();
        public string Info { get; set; }
      }
      public class Window36Behavior : Behavior<ListBox>
      {
        protected override void OnAttached()
        {
          AssociatedObject.PreviewMouseLeftButtonDown += AssociatedObject_PreviewMouseLeftButtonDown;
          AssociatedObject.DragEnter += AssociatedObject_DragEnter;
          AssociatedObject.Drop += AssociatedObject_Drop;
        }
    
        protected override void OnDetaching()
        {
          AssociatedObject.PreviewMouseLeftButtonDown -= AssociatedObject_PreviewMouseLeftButtonDown;
          AssociatedObject.DragEnter -= AssociatedObject_DragEnter;
          AssociatedObject.Drop -= AssociatedObject_Drop;
        }
    
        private void AssociatedObject_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
          TextBlock tb = AssociatedObject.InputHitTest(e.GetPosition(AssociatedObject)) as TextBlock;
          if (tb == null) return;
          string data = (tb.DataContext as Window36Data).ID.ToString();
          DragDrop.DoDragDrop(AssociatedObject, data, DragDropEffects.Move);
        }
    
        private void AssociatedObject_DragEnter(object sender, DragEventArgs e) => e.Effects = DragDropEffects.Move;
    
        private void AssociatedObject_Drop(object sender, DragEventArgs e)
        {
          // ViewModel
          Window36VM vm = AssociatedObject.DataContext as Window36VM;
          if (vm == null) return;
          // zu verschiebendes Object
          Guid id1 = Guid.Parse(e.Data.GetData(DataFormats.Text).ToString());
          Window36Data obj1 = (from item in vm.Collection where item.ID == id1 select item).FirstOrDefault();
          vm.Collection.Remove(obj1);
          // Ziel-Objekt
          TextBlock tb = AssociatedObject.InputHitTest(e.GetPosition(AssociatedObject)) as TextBlock;
          if (tb == null) return;
          Guid id2 = (tb.DataContext as Window36Data).ID;
          for (int i = 0; i < vm.Collection.Count; i++)
          {
            if (vm.Collection[i].ID == id2)
            {
              vm.Collection.Insert(i + 1, obj1);
              AssociatedObject.SelectedIndex = i + 1;
              break;
            }
          }
        }
      }
    }


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    Montag, 5. März 2018 21:30