Files
componentowl-astro/public/documentation/better-listview/data/chapter-drag-drop.html

480 lines
19 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:xlink="http://www.w3.org/1999/xlink">
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<title>Drag and Drop</title>
<link href="style.css" rel="stylesheet" type="text/css">
<link href="prettify.css" type="text/css" rel="stylesheet">
<script type="text/javascript" src="prettify.js"></script><script type="text/javascript" src="lang-vb.js"></script><link href="../resources/main.css" media="screen" rel="stylesheet" type="text/css">
</head>
<body onload="prettyPrint()"><div class="placing">
<br><table class="navigation"><tr>
<td class="navigation-previous"><a href="chapter-data.html"><strong>
« Data Binding</strong></a></td>
<td class="navigation-index"><a href="../../../quick-start-guide/better-listview/index.html"><strong>Index</strong></a></td>
<td class="navigation-next"><a href="chapter-embedded-controls.html"><strong>Embedded Controls »
</strong></a></td>
</tr></table>
<br><h1>Drag and Drop</h1>
<div class="banner">
<a href="../../../blog/page/6/index.html"><img src="../resources/overview.gif" alt="Better ListView" class="ss"></a>
<div class="inside">
<div class="text">Better ListView: Ultimate .NET ListView replacement control for WinForms (C#, VB.NET)</div>
<span class="dbtn-c dbtn-hilight"><span class="dbtn-w"><a href="../../../betterlistview.exe" class="dbtn">Download</a></span></span>
<span class="dbtn-c"><span class="dbtn-w"><a href="../../../blog/page/6/index.html" class="dbtn">More Info</a></span></span>
</div>
</div>
<p>The basic Drag and Drop functionality allows user to move data between
two controls: drag source and drop target. Regular .NET ListView does
support this basic Drag and Drop functionality, but not any additional (and
often pleasant) features based on Drag and Drop.</p>
<p>Better ListView adds these features:</p>
<ul>
<li>
<p>Item reordering</p>
</li>
<li>
<p>Drop highlighting</p>
</li>
<li>
<p>Insertion marks</p>
</li>
</ul>
<h2>Setting up Better ListView as a Drag Source</h2>
<p>Three properties are essential for setting up Better ListView as a
drag source:</p>
<ul style="list-style:none">
<li>
<span class="code">AllowedDragEffects</span><ul style="list-style:none"><li>
<p>Used when Drag and Drop operation is initiated. This tells the
Drag and Drop mechanism, what effects on mouse cursor can be shown
while dragging some data.</p>
</li></ul>
</li>
<li>
<span class="code">AllowDrag</span><ul style="list-style:none"><li>
<p>Simply switches the ability of Better ListView to behave as
drag source.</p>
</li></ul>
</li>
<li>
<span class="code">ItemReorderMode</span><ul style="list-style:none"><li>
<p>Sets the behavior of item reordering.</p>
</li></ul>
</li>
</ul>
<h2>Item Reordering</h2>
<p>Item reordering is enabled by setting <span class="code">ItemReorderMode</span>
property to either <span class="code">Enabled</span> or <span class="code">Custom</span>. The
difference between these values is that on <span class="code">Enabled</span> Better
ListView does all the item reordering automatically (items will be
actually reordered in the list), but <span class="code">Custom</span> shows only the
effect, fires item reorder events and the actual reordering is expected to
be done externally. This is practical - for example - when one displays
confirmation dialog to proceed reordering or just needs to deny the
reordering in some cases.</p>
<p>This image shows item reordering in action:</p>
<p class="images"><img src="drag-drop-reordering.png"></p>
<h2>Drag Effects</h2>
<p>There are two effect available while dragging over Better
ListView.</p>
<p><span class="code">DropHighlight</span> looks like a hot state of an item. It
shows when user is dragging data over an item. It is useful when data are
to be dropped on a certain item:</p>
<p class="images"><img src="drag-drop-dropeffect1.png"></p>
<p><span class="code">InsertionMark</span> is a line showing target position between
neighboring items. It is useful for inserting data in the list or item
reordering:</p>
<p class="images"><img src="drag-drop-dropeffect2.png"></p>
<p>When the <strong><em>InsertionMark</em></strong> effect is turned on, the
insertion mark is updated when mouse drags over the control. You may need
to set custom location of insertion mark in certain situations. In that
case, set the
<span class="code">BetterListViewDragDropEffectSettingEventArgs.UpdateInsertionMark</span>
property to false in the <span class="code">DragDropEffectSetting</span> event
handler.</p>
<h2>
<a name="internal-external-drop-display" id="internal-external-drop-display"></a>Internal and
External Drop Display</h2>
<p>There are two properties governing the effect during Drag and Drop
operation: <span class="code">ItemDropDisplayInternal</span> and
<span class="code">ItemDropDisplayExternal</span>.</p>
<p>Internal drop display is used when source and target of the
drag-drop operation is the same. This effect is <span class="code">InsertionMark</span>
by default and refers to item reordering.</p>
<p>External drop display is used when data are dragged from another
control. This effect is <span class="code">DropHighlight</span> by default.
<span class="code">DropHighlight</span> can be disabled on selected items by setting
<span class="code">AllowDropHighlight</span> property to <span class="code">false</span>.</p>
<h2>Customized Drop Display on Specific Items</h2>
<p>If you need to show different effects on specific items, you can use
properties <span class="code">BetterListViewItem.CustomDropDisplayInternal</span> and
<span class="code">BetterListViewItem.CustomDropDisplayExternal</span>. Their values
are initially set to <span class="code">BetterListViewDragDropDisplay.Default</span>,
which means that the values are derived from
<span class="code">ItemDropDisplayInternal</span> and
<span class="code">ItemDropDisplayExternal</span> properties instead (see <strong><em><a href="chapter-drag-drop.html#internal-external-drop-display">Internal and External Drop
Display</a></em></strong>).</p>
<h2>Default Format of Dragged Data</h2>
<p>Items can be dragged between different Better ListViews, other
controls and even across application domains (between applications).
Better ListView uses its own structure of type
<span class="code">BetterListViewItemDragData</span>.</p>
<p><span class="code">BetterListViewItemDragData</span> contains both dragged item
indices and cloned items. Items are cloned because when the dragged data
crosses application domain, it is serialized and must not contain any
reference to source Better ListView since such objects cannot be
transferred through this channel. For the purpose of indentifying drag
source control, <span class="code">BetterListViewItemDragData</span> contains
globally-unique ID of the Better ListView
(<span class="code">BetterListView.DragSourceID</span> property).</p>
<h2>Getting Insertion Location</h2>
<p>When doing item reordering, insertion location is available in
<span class="code">CheckItemReorder</span> even data
(<span class="code">BetterListViewCheckItemReorderEventArgs.InsertionLocation</span>)
so that you can decide whether to disable insertion mark or do other
action depending on current insertion location.</p>
<p>During Drag and Drop, however, there is no such data readily
available. The same functionality can be still achieved using
<span class="code">GetDropInfo</span> method. This method return insertion location
depending on current drag effect setting (drop highlight, insertion mark).
The parameters are screen coordinates of mouse cursor position (these are
readily available in the <span class="code">DragDropEffectSetting</span> event handler,
which you can use during Drag and Drop operation).</p>
<h2>Sample Source Code</h2>
<p><strong>C#</strong></p>
<pre class="prettyprint"><code class="lang-cs">//
// setup the first Better ListView
//
this.listView1.BeginUpdate();
this.listView1.Items.AddRange(
new[]
{
"A Fork",
"A Spoon",
"A Knife"
});
this.listView1.AutoSizeItemsInDetailsView = true;
this.listView1.EndUpdate();
// allow dragging items from this list
this.listView1.AllowDrag = true;
// allow dropping items on this list
this.listView1.AllowDrop = true;
// show insertion mark when dragging over this list
this.listView1.ItemDropDisplayExternal = BetterListViewDragDropDisplay.InsertionMark;
// this event has to be handled to properly set some effect (e.g. 'Move') when dragging
this.listView1.DragDropEffectSetting += ListViewDragDropEffectSetting;
// this event tells us that user dropped data on some item of the Better ListView (DragDrop event is more general than this)
this.listView1.ItemDrop += ListViewItemDrop;
// handle the case when user drops item(s) on empty list - in that case ItemDrop is not raised and we should use DragDrop
this.listView1.DragDrop += ListViewDragDrop;
//
// setup the second Better ListView
//
this.listView2.BeginUpdate();
this.listView2.Items.AddRange(
new[]
{
"A Chair",
"A Table",
"A Wardrobe"
});
this.listView2.AllowDrag = true;
this.listView2.AllowDrop = true;
this.listView2.ItemDropDisplayExternal = BetterListViewDragDropDisplay.InsertionMark;
this.listView2.AutoSizeItemsInDetailsView = true;
this.listView2.EndUpdate();
this.listView2.DragDropEffectSetting += ListViewDragDropEffectSetting;
this.listView2.ItemDrop += ListViewItemDrop;
this.listView2.DragDrop += ListViewDragDrop;</code></pre>
<p><strong>Visual Basic</strong></p>
<pre class="prettyprint"><code class="lang-vb">'
' setup the first Better ListView
'
ListView1.BeginUpdate()
ListView1.Items.AddRange(
New String() {
"A Fork",
"A Spoon",
"A Knife"
})
ListView1.AutoSizeItemsInDetailsView = True
ListView1.EndUpdate()
' allow dragging items from this list
ListView1.AllowDrag = True
' allow dropping items on this list
ListView1.AllowDrop = True
' show insertion mark when dragging over this list
ListView1.ItemDropDisplayExternal = BetterListViewDragDropDisplay.InsertionMark
' this event has to be handled to properly set some effect (e.g. 'Move') when dragging
AddHandler ListView1.DragDropEffectSetting, AddressOf ListViewDragDropEffectSetting
' this event tells us that user dropped data on some item of the Better ListView (DragDrop event is more general than this)
AddHandler ListView1.ItemDrop, AddressOf ListViewItemDrop
' handle the case when user drops item(s) on empty list - in that case ItemDrop is not raised and we should use DragDrop
AddHandler ListView1.DragDrop, AddressOf ListViewDragDrop
'
' setup the second Better ListView
'
ListView2.BeginUpdate()
ListView2.Items.AddRange(
New String() {
"A Chair",
"A Table",
"A Wardrobe"
})
ListView2.AllowDrag = True
ListView2.AllowDrop = True
ListView2.ItemDropDisplayExternal = BetterListViewDragDropDisplay.InsertionMark
ListView2.AutoSizeItemsInDetailsView = True
ListView2.EndUpdate()
AddHandler ListView2.DragDropEffectSetting, AddressOf ListViewDragDropEffectSetting
AddHandler ListView2.ItemDrop, AddressOf ListViewItemDrop
AddHandler ListView2.DragDrop, AddressOf ListViewDragDrop</code></pre>
<p>Source code for the <span class="code">ListViewDragDropEffectSetting</span>
event:</p>
<p><strong>C#</strong></p>
<pre class="prettyprint"><code class="lang-cs">void ListViewDragDropEffectSetting(object sender, BetterListViewDragDropEffectSettingEventArgs eventArgs)
{
BetterListViewItemDragData itemDragData = (BetterListViewItemDragData)eventArgs.Data.GetData(typeof(BetterListViewItemDragData));
Control child = GetChildAtPoint(PointToClient(new Point(eventArgs.X, eventArgs.Y)));
if (child is BetterListView &amp;&amp;
((BetterListView)child).DragSourceID == itemDragData.DragSourceID) // check whether the data comes from this cotnrol
{
// do not allow dropping on the source control
eventArgs.Effect = DragDropEffects.None;
}
else
{
eventArgs.Effect = DragDropEffects.Move;
}
}</code></pre>
<p><strong>Visual Basic</strong></p>
<pre class="prettyprint"><code class="lang-vb">Sub ListViewDragDropEffectSetting(ByVal sender As Object, ByVal eventArgs As BetterListViewDragDropEffectSettingEventArgs)
Dim itemDragData As BetterListViewItemDragData = DirectCast(eventArgs.Data.GetData(GetType(BetterListViewItemDragData)), BetterListViewItemDragData)
Dim child As Control = GetChildAtPoint(PointToClient(New Point(eventArgs.X, eventArgs.Y)))
If TypeOf child Is BetterListView.BetterListView AndAlso DirectCast(child, BetterListView.BetterListView).DragSourceID = itemDragData.DragSourceID Then
' check whether the data comes from this cotnrol
' do not allow dropping on the source control
eventArgs.Effect = DragDropEffects.None
Else
eventArgs.Effect = DragDropEffects.Move
End If
End Sub</code></pre>
<p>Source code for the <span class="code">ListViewItemDrop</span> event:</p>
<p><strong>C#</strong></p>
<pre class="prettyprint"><code class="lang-cs">void ListViewItemDrop(object sender, BetterListViewItemDropEventArgs eventArgs)
{
BetterListViewItemDragData itemDragData = (BetterListViewItemDragData)eventArgs.Data.GetData(typeof(BetterListViewItemDragData));
BetterListView listViewSource = GetSourceList(itemDragData);
BetterListView listViewTarget = GetTargetList(itemDragData);
// remove items from the source list
listViewSource.Items.RemoveRange(itemDragData.Items);
// insert items to the target list (either before or after the target item, depending on the insertion location)
listViewTarget.Items.InsertRange(
(eventArgs.ItemDropPart == BetterListViewDropPart.After)
? (eventArgs.Item.Index + 1)
: eventArgs.Item.Index,
itemDragData.Items);
}</code></pre>
<p><strong>Visual Basic</strong></p>
<pre class="prettyprint"><code class="lang-vb">Sub ListViewItemDrop(ByVal sender As Object, ByVal eventArgs As BetterListViewItemDropEventArgs)
Dim itemDragData As BetterListViewItemDragData = DirectCast(eventArgs.Data.GetData(GetType(BetterListViewItemDragData)), BetterListViewItemDragData)
Dim listViewSource As BetterListView.BetterListView = GetSourceList(itemDragData)
Dim listViewTarget As BetterListView.BetterListView = GetTargetList(itemDragData)
' remove items from the source list
listViewSource.Items.RemoveRange(itemDragData.Items)
' insert items to the target list (either before or after the target item, depending on the insertion location)
listViewTarget.Items.InsertRange(If((eventArgs.ItemDropPart = BetterListViewDropPart.After), (eventArgs.Item.Index + 1), eventArgs.Item.Index), itemDragData.Items)
End Sub</code></pre>
<p>Source code for the <span class="code">ListViewDragDrop</span> event:</p>
<p><strong>C#</strong></p>
<pre class="prettyprint"><code class="lang-cs">void ListViewDragDrop(object sender, DragEventArgs e)
{
BetterListViewItemDragData itemDragData = (BetterListViewItemDragData)e.Data.GetData(typeof(BetterListViewItemDragData));
BetterListView listViewSource = GetSourceList(itemDragData);
BetterListView listViewTarget = GetTargetList(itemDragData);
if (listViewTarget.Items.Count == 0)
{
// remove items from the source list
listViewSource.Items.RemoveRange(itemDragData.Items);
// add items to the target list
listViewTarget.Items.AddRange(itemDragData.Items);
}
}</code></pre>
<p><strong>Visual Basic</strong></p>
<pre class="prettyprint"><code class="lang-vb">Sub ListViewDragDrop(ByVal sender As Object, ByVal e As DragEventArgs)
Dim itemDragData As BetterListViewItemDragData = DirectCast(e.Data.GetData(GetType(BetterListViewItemDragData)), BetterListViewItemDragData)
Dim listViewSource As BetterListView.BetterListView = GetSourceList(itemDragData)
Dim listViewTarget As BetterListView.BetterListView = GetTargetList(itemDragData)
If listViewTarget.Items.Count = 0 Then
' remove items from the source list
listViewSource.Items.RemoveRange(itemDragData.Items)
' add items to the target list
listViewTarget.Items.AddRange(itemDragData.Items)
End If
End Sub</code></pre>
<p>Source code for the <span class="code">GetSourceList</span> and
<span class="code">GetTargetList</span> methods:</p>
<p><strong>C#</strong></p>
<pre class="prettyprint"><code class="lang-cs">BetterListView GetSourceList(BetterListViewItemDragData itemDragData)
{
return ((itemDragData.DragSourceID == this.listView1.DragSourceID) // check whether the data comes from the first ListView
? this.listView1
: this.listView2);
}
BetterListView GetTargetList(BetterListViewItemDragData itemDragData)
{
return ((itemDragData.DragSourceID == this.listView1.DragSourceID) // check whether the data comes from the first ListView
? this.listView2
: this.listView1);
}</code></pre>
<p><strong>Visual Basic</strong></p>
<pre class="prettyprint"><code class="lang-vb">Function GetSourceList(ByVal itemDragData As BetterListViewItemDragData) As BetterListView.BetterListView
' check whether the data comes from the first ListView
Return (If((itemDragData.DragSourceID = ListView1.DragSourceID), ListView1, ListView2))
End Function
Function GetTargetList(ByVal itemDragData As BetterListViewItemDragData) As BetterListView.BetterListView
' check whether the data comes from the first ListView
Return (If((itemDragData.DragSourceID = ListView1.DragSourceID), ListView2, ListView1))
End Function</code></pre>
<br><div class="banner">
<a href="../../../blog/page/6/index.html"><img src="../resources/overview.gif" alt="Better ListView" class="ss"></a>
<div class="inside">
<div class="text">Better ListView: Ultimate .NET ListView replacement control for WinForms (C#, VB.NET)</div>
<span class="dbtn-c dbtn-hilight"><span class="dbtn-w"><a href="../../../betterlistview.exe" class="dbtn">Download</a></span></span>
<span class="dbtn-c"><span class="dbtn-w"><a href="../../../blog/page/6/index.html" class="dbtn">More Info</a></span></span>
</div>
</div>
<table class="navigation"><tr>
<td class="navigation-previous"><a href="chapter-data.html"><strong>
« Data Binding</strong></a></td>
<td class="navigation-index"><a href="../../../quick-start-guide/better-listview/index.html"><strong>Index</strong></a></td>
<td class="navigation-next"><a href="chapter-embedded-controls.html"><strong>Embedded Controls »
</strong></a></td>
</tr></table>
<br><table class="footer"><tr>
<td class="footer-title">Better ListView Documentation
</td>
<td class="footer-copyright">
Copyright © 2010-2012  <a href="../../../index.html" target="_blank">ComponentOwl.com</a>
</td>
</tr></table>
</div></body>
</html>