2016-12-26 2 views
0

Anfänger hier.WPF Drag & Drop-Objekt aus Listbox

Ich versuche, eine Benutzersteuerung mit einer Listbox unter anderen Steuerelement zu erstellen, und ich möchte diese Listbox Drag-and-Drop zu anderen ähnlichen Instanz der Benutzersteuerung zulassen.

Dies ist das Objekt, das ich von einem listbox zum anderen ziehen und ablegen wollen:

[Serializable] 
public class ListBoxFileName : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    private void NotifyPropertyChanged(String info) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(info)); 
     } 
    } 

    private string FileNameValue; 
    public string FileName 
    { 
     get { return this.FileNameValue; } 

     set 
     { 
      if (value != this.FileNameValue) 
      { 
       this.FileNameValue = value; 
       NotifyPropertyChanged("FileName"); 
      } 
     } 
    } 

    private bool FileIsSelectedValue; 
    public bool FileIsSelected 
    { 
     get { return this.FileIsSelectedValue; } 

     set 
     { 
      if (value != this.FileIsSelectedValue) 
      { 
       this.FileIsSelectedValue = value; 
       NotifyPropertyChanged("FileIsSelected"); 
      } 
     } 
    } 
} 

Hier ist, wie ich mit der Drag & Drop befassen:

private ListBoxItem _dragged; 

    private void FileNameList_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
    { 
     if (_dragged != null) 
      return; 

     UIElement element = FileNameList.InputHitTest(e.GetPosition(FileNameList)) as UIElement; 
     while (element != null) 
     { 
      if (element is ListBoxItem) 
      { 
       _dragged = (ListBoxItem)element; 
       break; 
      } 
      element = VisualTreeHelper.GetParent(element) as UIElement; 
     } 
    } 


    private void Window_MouseMove(object sender, MouseEventArgs e) 
    { 
     if (_dragged == null) 
      return; 
     if (e.LeftButton == MouseButtonState.Released) 
     { 
      _dragged = null; 
      return; 
     } 
     DataObject obj = new DataObject(DataFormats.Serializable, _dragged); 
     DragDrop.DoDragDrop(_dragged, obj, DragDropEffects.All); 
    } 

    private void FileNameList_DragEnter(object sender, DragEventArgs e) 
    { 
     if (_dragged == null || e.Data.GetDataPresent(DataFormats.Serializable, true) == false) 
      e.Effects = DragDropEffects.None; 
     else 
      e.Effects = DragDropEffects.All; 
    } 

    private void FileListBox_Drop(object sender, DragEventArgs e) 
    { 
     if (e.Data.GetDataPresent(DataFormats.FileDrop, true)) 
     { 
      string[] droppedFilePaths = e.Data.GetData(DataFormats.FileDrop, true) as string[]; 
      for (var i = 0; i < droppedFilePaths.Length; i++) 
      { 
       ListBoxFileName filename = new ListBoxFileName(); 
       filename.FileName = droppedFilePaths[i]; 
       filename.FileIsSelected = false; 
       FileNamesItems.Add(filename); 
      } 
     } 
     if (e.Data.GetDataPresent(DataFormats.Serializable, true)) 
     { 
      ListBoxFileName BoxItem = new ListBoxFileName(); 
      BoxItem = e.Data.GetData(DataFormats.Serializable) as ListBoxFileName; 
     } 
    } 

Alles ist in Ordnung, außer wenn Das Drop-Ereignis tritt auf, BoxItem ist aus irgendeinem Grund immer Null, daher wird der Listbox nichts hinzugefügt.

Irgendwelche Hinweise?

Danke

+0

Haben Sie gong-wpf-dragdrop aus https://www.nuget.org/packages/gong-wpf-dragdrop/ probiert? Quellcode ist auch verfügbar, so dass Sie sehen können, wie es implementiert wurde – bamanow

+0

@bamanow, das nugget von gong-wpf hängt vom WPFToolkit-Paket ab, und dieses Paket hängt von .NET 3.5 ab. Es ist nicht kompatibel mit .NET 4.0 oder höher. –

+0

@Eriawan du irrst dich, stattdessen mit .NET 4.0 hat es keine Abhängigkeiten – bamanow

Antwort

1

Die Daten des Datenobjekts sollte anstelle eines ListBoxItem ein ListBoxFileName sein:

private void Window_MouseMove(object sender, MouseEventArgs e) 
{ 
    if (_dragged == null) 
     return; 
    if (e.LeftButton == MouseButtonState.Released) 
    { 
     _dragged = null; 
     return; 
    } 
    DataObject obj = new DataObject(DataFormats.Serializable, _dragged.DataContext as ListBoxFileName); 
    DragDrop.DoDragDrop(_dragged, obj, DragDropEffects.All); 
} 

private void FileListBox_Drop(object sender, DragEventArgs e) 
{ 
    if (e.Data.GetDataPresent(DataFormats.Serializable, true)) 
    { 
     ListBoxFileName BoxItem = e.Data.GetData(DataFormats.Serializable) as ListBoxFileName; 
     //... 
    } 
} 

Dies sollte unter der Annahme arbeiten, dass die Itemssource des „FileNameList“ Kontrolle in ein IEnumerable gesetzt.

Bitte geben Sie alle relevanten Code-Snippets an, die erforderlich sind, um Ihr Problem von Grund auf reproduzieren zu können, wenn Sie weitere Hilfe dazu benötigen.

+0

Dank es ist "teilweise" funktioniert. In der Tat, wenn ich jetzt eine der Kopien eines BoxItems auswähle, dann wird es in jeder Listbox ausgewählt. Irgendeine Idee wo das herkommen könnte? – lecloneur

+0

Dasselbe ListBoxFileName-Objekt ist der DataContext der zwei verschiedenen visuellen Container. Wenn Sie also die IsSelected-Eigenschaft (oder wie immer Sie es nennen) festlegen, werden beide Container ausgewählt, da sie an dieselbe Eigenschaft gebunden sind. Wenn Sie dies nicht möchten, sollten Sie das ListBoxFileName-Objekt klonen, d. H. Eine Kopie erstellen, bevor Sie es der zweiten ListBox hinzufügen. – mm8

+0

es funktioniert, danke – lecloneur