2016-12-26 2 views
0

начинающий здесь.WPF Drag and Drop объект из списка

Я пытаюсь создать usercontrol с одним списком среди другого элемента управления, и я хочу, чтобы этот список позволял перетаскивать и другие аналогичные экземпляры usercontrol.

Это объект, который я хочу, чтобы перетащить из одного ListBox к другому:

[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"); 
      } 
     } 
    } 
} 

Вот как я имею дело с перетаскиванием:

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; 
     } 
    } 

Все это хорошо, за исключением, когда происходит событие переадресации, BoxItem всегда по умолчанию является нулевым, поэтому в список ничего не добавляется.

Подсказка?

Спасибо

+0

Вы пробовали gong-wpf-dragdrop с https://www.nuget.org/packages/gong-wpf-dragdrop/? Исходный код также доступен, поэтому вы можете посмотреть, как он был реализован. – bamanow

+0

@bamanow, nuget gong-wpf зависит от пакета WPFToolkit, и этот пакет зависит от .NET 3.5. Он несовместим с .NET 4.0 или новее. –

+0

@ Eriawan, вы ошибаетесь, вместо этого с .NET 4.0 у него нет зависимостей – bamanow

ответ

1

Данные DataObject должны быть ListBoxFileName вместо ListBoxItem:

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; 
     //... 
    } 
} 

Это должно работать при условии, что ItemsSource контроля «FileNameList» устанавливается в IEnumerable.

Просьба предоставить все соответствующие фрагменты кода, необходимые для воспроизведения вашей проблемы с нуля, если вам нужна дополнительная помощь по этому вопросу.

+0

, потому что это «частично» работает. Действительно, теперь, когда я выбираю одну из копий BoxItem, она выбирается в каждом списке. Любая идея, откуда это может произойти? – lecloneur

+0

Тот же объект ListBoxFileName представляет собой DataContext двух разных визуальных контейнеров, поэтому, когда вы устанавливаете его свойство IsSelected (или как вы его называете), оба контейнера будут выбраны, так как они привязаны к одному и тому же свойству. Если вы не хотите этого, вы должны клонировать, т. Е. Создать копию объекта ListBoxFileName, прежде чем добавлять его во второй ListBox. – mm8

+0

Это работает, спасибо – lecloneur