Drag & Drop auf Listbox

  • WPF

Es gibt 12 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    Drag & Drop auf Listbox

    Hallo Ihr Lieben,

    ich habe diesen Thread eröffnet, da alle Tutorials die ich auf google gefunden habe augenscheinlich im Codebehind arbeiten, aber ich verwende ja eigentlich ausschließlich ein ViewModel. Gibt es Eures Wissens nach ein Tutorial welches D&D in Verbindung mit einem ViewModel erklärt, oder muss ich dann ein UCL mit Codebehind erstellen um das nutzen zu können?

    Hintergrund, ich muss (für die Arbeit) einige PDF-Dateien laden, aus denen will ich am Ende bestimmte vorgefertigte Outlook-Drafts generieren lassen (das muss ich auch erstmal irgendwo nachforschen ist aber noch nicht ganz Thema ^^). Per D&D soll erstmal nur der Pfad (Dateien sollen im Draft als Anhang genutzt werden) und der Dateiname ausgelesen werden, sodass ich die Files als Item in eine Listbox laden kann, pro Item will ich dann die Empfänger Mail-Adresse hinterlegen, und den Empfängernamen, sodass ich das nicht wie bisher mal eben für 50 Files in 50 Mails von Hand machen muss (geht um Rechnungsversand).

    Habt Ihr hierzu gute Quellen oder ein paar Ideen wie das zu bewerkstelligen ist/wäre?

    Vielen Dank im voraus
    AsusDK
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If
    Ich verstosse bei D&D ganz krass gegen das MVVM-Dogma, dass im Viewmodel keine Controls vorkommen dürfen.
    Weil für D&D brauche ich verschiedenerlei Events, und die kriege ich numal nur vonne Controls: MouseDown, MouseUp, MouseMove, und vlt. sogar noch paar mehr.
    Ich hab mir ein Property im VM gebaut, da binde ich einen Treeview dran, und dann schnapp ich mir den im Viewmodel, und abonniere dort seine Events - wie ichs halt brauche.

    Auf diese Weise läuft bei mir auch das D&D ohne Codebehind ab.

    Ist numal so: Bei D&D muss man View und Viewmodel enger als sonst zusammenbringen.
    D.h. entweder das Viewmodel ins View (Codebehind) oder das View ins Viewmodel.

    Ich kann mal raussuchen, was ih dazu verzapft habe - ist darüberhinaus noch urs kompliziert - weil man da schwer im VisualTree drin herum-agieren muss.
    Und mit Adornern und so dolle Sachn.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Bei meinem aktuellen Projekt habe ich Drag&Drop innerhalb der Anwendung. Dafür habe ich zwei Behaviors geschrieben. Einmal DropTargetBehaviour und einmal DragSourceBehaviour. Damit kann man bequem im XAML ein Steuerelement als DragSource oder DropTarget (oder beides) festlegen. Die DragSource hat sogar eine hübsche Preview beim Draggen. Das Viewmodel hat dann einfach ein DropCommand welches ans DropTarget der View gebunden wird. Man kann Zieltyp(DataType), Effects ect einstellen.

    Also über Behaviors lässt sich das sehr elegant und ohne viel Code lösen.
    Hm, dann wäre evtl. doch ein einfacher OpenFileDialog sinnvoller, obwohl das mit den Behaviors interessant klingt, hab jetzt nur leider noch kein Besipiel gefunden in welchen Behaviors für D&D genutzt werden, kannst du evtl. einen kleinen Samplecode posten @Gonger96 ?

    Lg und Danke euch beiden
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If
    Ich hab hier mal ein Minimalbeispiel hochgeladen. Das ist nur ein reiner FileDrop, lässt sich aber vom Prinzip auf eine sehr komplexe D&D Anwendung erweitern.
    Dateien
    Hm, leider befürchte ich das Behaviors nur in C# zur Verfügung stehen ? denn Trotz aller imports wird behavior nicht akzeptiert...


    Nachtrag: ok, hab nach einigem rumprobieren herausgefunden das das ein extra Nuggetpaket benötigt, nicht schön aber ok.

    allerdings funktionieren diese beiden Teile nicht:

    VB.NET-Quellcode

    1. ​Protected Overrides Sub OnAttached()
    2. MyBase.OnAttached()
    3. AssociatedObject.DragOver += AddressOf AssociatedObject_DragOver
    4. AssociatedObject.DragEnter += AddressOf AssociatedObject_DragOver
    5. AssociatedObject.Drop += AddressOf AssociatedObject_Drop
    6. End Sub
    7. Protected Overrides Sub OnDetaching()
    8. AssociatedObject.DragOver -= AddressOf AssociatedObject_DragOver
    9. AssociatedObject.DragEnter -= AddressOf AssociatedObject_DragOver
    10. AssociatedObject.Drop -= AddressOf AssociatedObject_Drop
    11. MyBase.OnDetaching()
    12. End Sub


    Public Event DragOver as DragEventhandler ist ein ereignis und kann nicht direkt aufgerufen werden, verwenden Sie die RaiseEvent-Anweisung, allerding hab ich jede für mich erdenkliche Schreibweise versucht, ich bekomm das nicht zum laufen....
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „asusdk“ ()

    Ich hatte extra die Projektmappe angehangen. Du brauchst einen Verweis auf Microsoft.Xaml.Behaviors.WPF . Einfach das Nuget-Packet hinzufügen.
    [url=https://devblogs.microsoft.com/dotnet/open-sourcing-xaml-behaviors-for-wpf/#:~:text=XAML%20Behaviors%20for%20WPF%20now%20ships%20as%20a,it%20can%20be%20consumed%20and%20used%20almost%20immediately.]Link[/url]
    Ja das hab ich mittlerweile rausbekommen, durch exzessives googeln, keine Ahnung wie ich das Anhand der Projektmappe hätte sehen sollen ?, aber siehe Nachtrag oben, ich bekomms leider dennoch nicht zum laufen.

    Danke dir auf jeden Fall =)
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If
    Hm gut, das hab ich bisher noch nie hinbekommen, das HandlerZeug hab ich noch nie begriffen. Dennoch Danke =) Muss halt ein OpenFileDialog herhalten

    Gesetzt dem Fall das es so richtig angewendet ist:

    VB.NET-Quellcode

    1. ​Protected Overrides Sub OnAttached()
    2. MyBase.OnAttached()
    3. AddHandler AssociatedObject.DragOver, New DragEventHandler(AddressOf AssociatedObject_DragOver)
    4. AddHandler AssociatedObject.DragEnter, New DragEventHandler(AddressOf AssociatedObject_DragOver)
    5. AddHandler AssociatedObject.Drop, New DragEventHandler(AddressOf AssociatedObject_DragOver)
    6. End Sub
    7. Protected Overrides Sub OnDetaching()
    8. MyBase.OnDetaching()
    9. RemoveHandler AssociatedObject.DragOver, New DragEventHandler(AddressOf AssociatedObject_DragOver)
    10. RemoveHandler AssociatedObject.DragEnter, New DragEventHandler(AddressOf AssociatedObject_DragOver)
    11. RemoveHandler AssociatedObject.Drop, New DragEventHandler(AddressOf AssociatedObject_DragOver)
    12. End Sub


    krieg ich es unter VB trotzdem ums verrecken nicht zum laufen, aht evtl. jemand ein funktionierendes VB beispiel, das convertieren scheint einfach nicht zu funktionieren
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „asusdk“ ()

    Ok, Gong.WPF.DragDrop ist die Lösung. Per Nugget Manager installieren: Gong WPF DragDrop

    im wpf, test Listbox:

    XML-Quellcode

    1. <Window x:Class="MainWindow"
    2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    4. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    5. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    6. xmlns:local="clr-namespace:Autolook"
    7. xmlns:dragDrop="clr-namespace:GongSolutions.Wpf.DragDrop;assembly=GongSolutions.Wpf.DragDrop"
    8. mc:Ignorable="d"
    9. Title="MainWindow" Height="450" Width="800">
    10. <Window.DataContext>
    11. <local:TestViewmodel/>
    12. </Window.DataContext>
    13. <Grid>
    14. <ListBox ItemsSource="{Binding Filenames}"
    15. dragDrop:DragDrop.IsDropTarget="True"
    16. dragDrop:DragDrop.DropHandler="{Binding}"/>
    17. </Grid>
    18. </Window>


    im ViewModel:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System
    2. Imports System.Collections.Generic
    3. Imports System.Collections.ObjectModel
    4. Imports System.Linq
    5. Imports System.Text
    6. Imports System.Threading.Tasks
    7. Imports GongSolutions.Wpf.DragDrop
    8. Public Class TestViewmodel
    9. Inherits BaseViewModel
    10. Implements IDropTarget
    11. Private _fileNames As ObservableCollection(Of String) = New ObservableCollection(Of String)
    12. Public Property Filenames() As ObservableCollection(Of String)
    13. Get
    14. Return _fileNames
    15. End Get
    16. Set(ByVal value As ObservableCollection(Of String))
    17. ChangePropIfDifferent(value, _fileNames)
    18. End Set
    19. End Property
    20. Private Sub IDropTarget_DragOver(dropInfo As IDropInfo) Implements IDropTarget.DragOver
    21. dropInfo.DropTargetAdorner = DropTargetAdorners.Insert
    22. Dim dataObject = TryCast(dropInfo.Data, IDataObject)
    23. If dataObject IsNot Nothing AndAlso dataObject.GetDataPresent(DataFormats.FileDrop) Then
    24. dropInfo.Effects = DragDropEffects.Copy
    25. Else
    26. dropInfo.Effects = DragDropEffects.Move
    27. End If
    28. End Sub
    29. Private Sub IDropTarget_Drop(dropInfo As IDropInfo) Implements IDropTarget.Drop
    30. Dim dataObject = TryCast(dropInfo.Data, DataObject)
    31. If dataObject IsNot Nothing AndAlso dataObject.ContainsFileDropList() Then
    32. For Each s As String In dataObject.GetFileDropList
    33. 'MessageBox.Show(s)
    34. Filenames.Add(s)
    35. Next
    36. End If
    37. End Sub
    38. End Class
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If

    asusdk schrieb:

    Hm, leider befürchte ich das Behaviors nur in C# zur Verfügung stehen ?
    Achtung!
    Behavior ist ein EntwurfsPattern, mit dem man die Funktionalität von Klassen erweitern kann, ohne sie zu beerben:
    Das Behavior bekommt ein Objekt übergeben und abonniert dessen Events, und macht da iwas Behavior-Spezifisches.
    Etwa ein "D&D-Behavior" mag diverse Mouse-Events eines Controls abonnieren, und damit D&D umsetzen.
    Fabelhafte Sache sowas:
    Dem D&D-Behavior kannst du ein Label übergeben, und dann kann das Label D&D (weil das Behavior die entsprechenden Mouse-Events in geeigneter Weise verarbeitet).
    Übergib dem Behavior einen Treeview, dann kann der TV D&D.
    Mittm Behavior-Pattern kann man logischerweise nur Klassen erweitern, die Events verschicken - aber zB. bei Controls aller Art (bzw 'Visuals' in WPF) kann man sich vor Events ja kaum retten.

    Wenns eine Dll gibt (oder ein Nuget-Paket), die 'Behavior' im Namen führt, dann wird die sich wohl mit solchen Sachen auseinandersetzen, und iwie unterstützen.
    Aber die dll hat nicht den EntwurfsPattern für sich gepachtet, sondern jeder, der den Pattern kapiert hat, kann seine eigenen Behaviors schreiben.

    Und in WPF kann man AttachedProperties bauen, welche Behaviors sind, und daran im XAML Controls anbinden.
    Zeigt sich malwieder: WPF hat wirklich allerlei echt schnucklige und mächtige Konzepte.