Files

442 lines
18 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-listview-express/documentation.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>
<br><hr>
<p class="note">Item reordering feature is not supported in <strong><em>Better
ListView Express</em></strong>.</p>
<hr>
<br><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>
<h2>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>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>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="../../../better-listview-express/documentation.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 Express Documentation
</td>
<td class="footer-copyright">
Copyright © <a href="../../../index.html" target="_blank">ComponentOwl.com</a>
</td>
</tr></table>
</div></body>
</html>