480 lines
19 KiB
HTML
480 lines
19 KiB
HTML
<!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="../../../better-thumbnail-browser/documentation.html"><strong>Index</strong></a></td>
|
||
<td class="navigation-next"><a href="chapter-empty-text.html"><strong>Empty Text »
|
||
</strong></a></td>
|
||
</tr></table>
|
||
<br><h1>Drag and Drop</h1>
|
||
<div class="banner">
|
||
<a href="../../../better-thumbnail-browser.html"><img src="../resources/better-thumbnail-browser-overview.gif" alt="Better Thumbnail Browser" class="ss"></a>
|
||
<div class="inside">
|
||
<div class="text">Better Thumbnail Browser for .NET (C#, VB) - Image thumbnail viewing and loading control</div>
|
||
<span class="dbtn-c dbtn-hilight"><span class="dbtn-w"><a href="../../../betterthumbnailbrowser.exe" class="dbtn">Download</a></span></span>
|
||
<span class="dbtn-c"><span class="dbtn-w"><a href="../../../better-thumbnail-browser.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 &&
|
||
((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="../../../better-thumbnail-browser.html"><img src="../resources/better-thumbnail-browser-overview.gif" alt="Better Thumbnail Browser" class="ss"></a>
|
||
<div class="inside">
|
||
<div class="text">Better Thumbnail Browser for .NET (C#, VB) - Image thumbnail viewing and loading control</div>
|
||
<span class="dbtn-c dbtn-hilight"><span class="dbtn-w"><a href="../../../betterthumbnailbrowser.exe" class="dbtn">Download</a></span></span>
|
||
<span class="dbtn-c"><span class="dbtn-w"><a href="../../../better-thumbnail-browser.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="../../../better-thumbnail-browser/documentation.html"><strong>Index</strong></a></td>
|
||
<td class="navigation-next"><a href="chapter-empty-text.html"><strong>Empty Text »
|
||
</strong></a></td>
|
||
</tr></table>
|
||
<br><table class="footer"><tr>
|
||
<td class="footer-title">Better Thumbnail Browser Documentation
|
||
</td>
|
||
<td class="footer-copyright">
|
||
Copyright © 2010-2012 <a href="../../../index.html" target="_blank">ComponentOwl.com</a>
|
||
</td>
|
||
</tr></table>
|
||
</div></body>
|
||
</html>
|