{"id":14986288,"url":"https://github.com/awaescher/fluentdragdrop","last_synced_at":"2025-04-06T14:11:06.346Z","repository":{"id":40351014,"uuid":"292379647","full_name":"awaescher/FluentDragDrop","owner":"awaescher","description":"🖱 The sexiest Drag\u0026Drop for WinForms on this planet.","archived":false,"fork":false,"pushed_at":"2024-05-10T22:35:56.000Z","size":33110,"stargazers_count":115,"open_issues_count":0,"forks_count":16,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-30T13:08:12.245Z","etag":null,"topics":["drag","drag-and-drop","drag-drop","drop","winforms"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/awaescher.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-09-02T19:46:31.000Z","updated_at":"2025-03-24T15:21:54.000Z","dependencies_parsed_at":"2024-05-10T10:42:43.266Z","dependency_job_id":"8a68308a-40c0-4369-8a76-02672f94767a","html_url":"https://github.com/awaescher/FluentDragDrop","commit_stats":{"total_commits":127,"total_committers":5,"mean_commits":25.4,"dds":"0.25196850393700787","last_synced_commit":"b0953115d528c10c6538f2bb665ecc418c1eae13"},"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/awaescher%2FFluentDragDrop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/awaescher%2FFluentDragDrop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/awaescher%2FFluentDragDrop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/awaescher%2FFluentDragDrop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/awaescher","download_url":"https://codeload.github.com/awaescher/FluentDragDrop/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247492513,"owners_count":20947544,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["drag","drag-and-drop","drag-drop","drop","winforms"],"created_at":"2024-09-24T14:12:38.992Z","updated_at":"2025-04-06T14:11:06.326Z","avatar_url":"https://github.com/awaescher.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Fluent Drag\u0026Drop\n\n[![NuGet Status](https://img.shields.io/nuget/v/FluentDragDrop.svg)](https://www.nuget.org/packages/FluentDragDrop/) \u003csup\u003e[🔆 Now with effects](#-effects)\u003c/sup\u003e\n\nDrag\u0026Drop in WinForms is cumbersome and error-prone. There are multiple events to handle, members to track and properties to set on at least two controls. Passing data is kind of special and you don't get preview images while dragging things around.\n\nWouldn't it be great if you could use Drag\u0026Drop with fluent code like this?\n\n\u003c!-- snippet: ImmediateUsage --\u003e\n\u003ca id='snippet-ImmediateUsage'\u003e\u003c/a\u003e\n```cs\nprivate void picControlPreviewBehindCursor_MouseDown(object sender, MouseEventArgs e)\n{\n\tvar pic = (PictureBox)sender;\n\n\tpic.InitializeDragAndDrop()\n\t\t.Copy()\n\t\t.Immediately()\n\t\t.WithData(pic.Image)\n\t\t.WithPreview().BehindCursor()\n\t\t.To(PreviewBoxes, (target, data) =\u003e target.Image = data);\n\n\t// Copy(), Move() or Link() to define allowed effects\n\t// Immediately() or OnMouseMove() for deferred start on mouse move\n\t// WithData() to pass any object you like\n\t// WithPreview() to define your preview and how it should behave\n\t//     BehindCursor() or RelativeToCursor() to define the preview placement\n\t// To() to define target controls and how the dragged data should be used on drop\n}\n```\n\u003csup\u003e\u003ca href='/src/FluentDragDropExample/TestForm.cs#L32-L51' title='Snippet source file'\u003esnippet source\u003c/a\u003e | \u003ca href='#snippet-ImmediateUsage' title='Start of snippet'\u003eanchor\u003c/a\u003e\u003c/sup\u003e\n\u003c!-- endSnippet --\u003e\n\nIt's all in there: Putting data to the drag\u0026drop operation, attaching a custom preview image to the mouse cursor, working with the dragged data once it's dropped and much more.\n\n![Screenshot](doc/PreviewDragStyles.gif)\n\n\u003e Did you notice that you can even update preview images and their opacity at any time while dragging? 😉\n\n## Perfect by default\n\nIn real world apps, Drag\u0026Drop should not start at MouseDown because the control selection might not be up to date to the mouse interaction. Instead, developers typically have to keep track that MouseDown did happen and add an additional event handler to MouseMove. If MouseMove is triggered and there was a MouseDown but no MouseUp, the user pressed the mouse button and moved the mouse. So that's when he wanted to start a Drag\u0026Drop operation.\n\nCareful developers won't track a flag whether the mouse button is still down or not but the location where the user pressed the button. On MouseMove, they can then calculate the distance how much the cursor did move. Having a few pixels buffer here helps to prevent the user from accidential Drag\u0026Drop operations. \n\nFluentDrag\u0026Drop does exactly that if defined with `OnMouseMove()`. However there is no flag or location to track. Methods like `WithData()` won't accept direct variables to be passed anymore, instead they require a function which gets called as soon as the mouse move is detected later on - if the user pressed and held the mouse button and if he moved a few pixels. Additionally, the developer has the possibility to validate the input like a valid control selection with `If()`. Of course, this gets called just like `WithData()` as soon as the user moves the mouse accordingly:\n\n\u003c!-- snippet: DelayedUsage --\u003e\n\u003ca id='snippet-DelayedUsage'\u003e\u003c/a\u003e\n```cs\nprivate void CountryList_MouseDown(object sender, MouseEventArgs e)\n{\n\tvar source = (ListView)sender;\n\tvar target = source.Equals(listLeft) ? listRight : listLeft;\n\n\tsource.InitializeDragAndDrop()\n\t\t.Move()\n\t\t.OnMouseMove()\n\t\t.If(() =\u003e source.SelectedIndices.Count \u003e 0)\n\t\t.WithData(() =\u003e source.SelectedItems.OfType\u003cListViewItem\u003e().ToArray())\n\t\t.WithPreview((_, data) =\u003e RenderPreview(data)).BehindCursor()\n\t\t.To(target, MoveItems);\n}\n```\n\u003csup\u003e\u003ca href='/src/FluentDragDropExample/TestForm.cs#L80-L94' title='Snippet source file'\u003esnippet source\u003c/a\u003e | \u003ca href='#snippet-DelayedUsage' title='Start of snippet'\u003eanchor\u003c/a\u003e\u003c/sup\u003e\n\u003c!-- endSnippet --\u003e\n\nThis (\u003csub\u003e\u003csup\u003eand the 5 line method `MoveItems()`\u003c/sub\u003e\u003c/sup\u003e) is everything we need to implement two-way Drag\u0026Drop lists:\n\n![Screenshot](doc/RealWorld.gif)\n\n## Compatibility\n\nFluentDrag\u0026Drop can easily be used with your current Drag\u0026Drop implementations if you want. The following animation shows how it works in combination with traditional Drag\u0026Drop implementations as we know with events like `DragEnter`, `DragOver` and `DragDrop`:\n\n![Screenshot](doc/Compatibility.gif)\n\n## Smoothness\n\nMost approaches I have used in the past get in trouble when moving the preview over controls that do not have the property `AllowDrop` set to `true`. Whenever a Drag\u0026Drop implementation uses the `GiveFeedback` event to update its preview images, you might get laggy Drag\u0026Drop experiences with stuttering preview image movements.\n\nIn contrast, FluentDrag\u0026Drop will render preview images smoothly wherever you move them, even over other applications.\n\n## 🔆 Effects\n\nTo make your drag and drop implementation even more impressive, this repository also contains a project called \"FluentDragDrop.Effects\". It is part of the FluentDrag\u0026Drop solution but builds to a separate and optional package which extends FluentDrag\u0026Drop with a set of default effects.\n\nSome of these effects are: \n- FadeIn\n- FadeOut\n- ReturnOnCancel\n- MorphToTarget\n\n![Effects](doc/Effects.gif)\n\nThe sample above shows some of the effects in action:\n- FadeIn on start\n- ReturnOnCancel when dropping next to the empty box\n- MorphToTarget when dropping into the empty box\n  - this effect is accompanied by an additional effect implemented in the sample app causing the box to fade a color\n\n### FluentTransitions\n\nThose effects are powered by another project called [FluentTransitions](https://github.com/awaescher/FluentTransitions) allowing the animations and transitions to be rendered smoothly. I'd encourage you to check it out:\n- [GitHub](https://github.com/awaescher/FluentTransitions)\n- [NuGet](https://www.nuget.org/packages/FluentTransitions)\n\n---\n\nImages taken from Unsplash, links to these are located at [/doc/Unsplash](/doc/Unsplash).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fawaescher%2Ffluentdragdrop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fawaescher%2Ffluentdragdrop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fawaescher%2Ffluentdragdrop/lists"}