I'm trying to add some DragDrop support to my forms and their RadTextBox (move/copy textbox content to another textbox only. Not a dragdop inside the same textbox).
I have some problems to start the operations because when an user make some mouse move with the left button pressed, the radtextbox start selecting the text from the pointer position (like Notepad do).
The perfect case is to have a behavior corresponding to the RadRichTextBox (or Microsoft Word). If you click and move when some text is selected, a dragdrop operation is started. If you click and move without any text selected, a selection operation is started (the current behavior).
Which event should I handle to make it work ? (RadTextbox mousemove don't trig, RadTextBox.TextBoxElement mouvemove do trigger but I can't get any information about the selected text from it !)
Thanks for reading
6 Answers, 1 is accepted
Thank you for writing.
Here is a sample code snippet, demonstrating how to achieve drag and drop from a RadTextBox to another RadTextBox, when there is selected text in the source RadTextBox:
public
Form1()
{
InitializeComponent();
this
.radTextBox1.TextBoxElement.AllowDrag =
true
;
this
.radTextBox1.TextBoxElement.MouseUp += TextBoxElement_MouseUp;
this
.radTextBox1.TextBoxElement.MouseDown += TextBoxElement_MouseDown;
this
.radTextBox2.TextBoxElement.TextBoxItem.HostedControl.AllowDrop =
true
;
this
.radTextBox2.TextBoxElement.TextBoxItem.HostedControl.DragEnter += HostedControl_DragEnter;
this
.radTextBox2.TextBoxElement.TextBoxItem.HostedControl.DragDrop += HostedControl_DragDrop;
}
int
selectionStart = 0;
int
selectionLength = 0;
string
selectedText =
string
.Empty;
private
void
TextBoxElement_MouseUp(
object
sender, MouseEventArgs e)
{
//keep the selected text
selectionStart =
this
.radTextBox1.SelectionStart;
selectionLength =
this
.radTextBox1.SelectionLength;
selectedText =
this
.radTextBox1.SelectedText;
}
private
void
TextBoxElement_MouseDown(
object
sender, MouseEventArgs e)
{
if
(e.Button == System.Windows.Forms.MouseButtons.Left && selectedText !=
string
.Empty)
{
this
.radTextBox1.SelectionStart = selectionStart;
this
.radTextBox1.SelectionLength = selectionLength;
this
.radTextBox1.DoDragDrop(
this
.radTextBox1.SelectedText, DragDropEffects.Move);
}
}
private
void
HostedControl_DragEnter(
object
sender, DragEventArgs e)
{
IDataObject dataObject = e.Data;
if
(dataObject ==
null
)
e.Effect = DragDropEffects.None;
else
{
string
draggedText = dataObject.GetData(
typeof
(
string
)).ToString();
if
(draggedText !=
null
&& draggedText !=
string
.Empty)
e.Effect = e.AllowedEffect;
else
e.Effect = DragDropEffects.None;
}
}
private
void
HostedControl_DragDrop(
object
sender, DragEventArgs e)
{
this
.radTextBox2.Text = (
string
)e.Data.GetData(DataFormats.Text);
selectedText =
string
.Empty;
}
I hope this information helps. Should you have further questions, I would be glad to help.
Regards,
Desislava
Telerik
Hi Desislava,
Thank you for your answer and your code sample.
I tested your solution over a sample projet with two RadTextBox. It's working fine except a little bug.
Select the text, then begin a dragdrop to an illegal destination (releasing the mouse not in the destination textbox).
After that when you click back on the first textbox, the selection is stuck. (certainly because the selectedText is not reset as you don't go in HostedConrol_DragDrop in this scenario).
As I have at least 32 RadTextBoxes on my form, I have tried to adapt your code for something more generic. Because I'm not really a big fan of writing 4 x 32 Sub for this.
The WireEvent_And_Configure_DragDropableRadTextBox() and the list are called on the constructor of the form.
My generic solution is a little buggy.
* The drag and drop do not start sometime (Text is selected instead of beginning DragDrop)
* Some Time the data are drop'ed' when I make a simple click on a Textbox.
Exemple:
I have a textbox with "Honolulu". I select the whole text with the mouse. I try to begin dragdrop but it's select half of the word instead ("Hono"). I click again to make a whole selection with the most and the text "Hono" is dropped on the textbox.
I think that's there is something to improve with the selectedText !
Private DragDropableRadTextBoxs As List(Of RadTextBox)
Private Sub WireEvent_And_Configure_DragDropableRadTextBox()
For Each aRadTextBox As RadTextBox In DragDropableRadTextBoxs
aRadTextBox.TextBoxElement.AllowDrag = True
aRadTextBox.TextBoxElement.TextBoxItem.HostedControl.AllowDrop = True
AddHandler aRadTextBox.TextBoxElement.MouseUp, AddressOf DragDropableRadTextBox_MouseUp
AddHandler aRadTextBox.TextBoxElement.MouseDown, AddressOf DragDropableRadTextBox_MouseDown
AddHandler aRadTextBox.TextBoxElement.TextBoxItem.HostedControl.DragEnter, AddressOf DragDropableRadTextBox_DragEnter
AddHandler aRadTextBox.TextBoxElement.TextBoxItem.HostedControl.DragDrop, AddressOf DragDropableRadTextBox_DragDrop
Next
End Sub
Private selectionStart As Integer = 0
Private selectionLength As Integer = 0
Private selectedText As String = String.Empty
Private Sub DragDropableRadTextBox_MouseUp(sender As System.Object, e As System.Windows.Forms.MouseEventArgs)
Dim TextBox As RadTextBox = CType(sender, RadTextBoxElement).TextBoxItem.HostedControl.Parent
selectionStart = TextBox.SelectionStart
selectionLength = TextBox.SelectionLength
selectedText = TextBox.SelectedText
End Sub
Private Sub DragDropableRadTextBox_MouseDown(sender As System.Object, e As System.Windows.Forms.MouseEventArgs)
If e.Button = Windows.Forms.MouseButtons.Left AndAlso selectedText <> String.Empty Then
Dim TextBox As RadTextBox = CType(sender, RadTextBoxElement).TextBoxItem.HostedControl.Parent
TextBox.SelectionStart = selectionStart
TextBox.SelectionLength = selectionLength
DoDragDrop(TextBox.SelectedText, DragDropEffects.Copy Or DragDropEffects.Move)
End If
End Sub
Private Sub DragDropableRadTextBox_DragEnter(sender As System.Object, e As System.Windows.Forms.DragEventArgs)
Dim dataObject As IDataObject = e.Data
If dataObject Is Nothing Then
e.Effect = DragDropEffects.None
Else
Dim draggedText As String = dataObject.GetData(GetType(String)).ToString()
If draggedText IsNot Nothing AndAlso draggedText <> String.Empty Then
e.Effect = e.AllowedEffect
Else
e.Effect = DragDropEffects.None
End If
End If
End Sub
Private Sub DragDropableRadTextBox_DragDrop(sender As System.Object, e As System.Windows.Forms.DragEventArgs)
Dim TextBox As RadTextBox = TryCast(sender.Parent, RadTextBox)
TextBox.Text &= CStr(e.Data.GetData(DataFormats.Text))
selectedText = String.Empty
End Sub
Thank you for writing back.
First to disable the text copying for the same text box you can check if the text is dropped in different text box within the DragDrop event:
Private
current
As
RadTextBox
Private
Sub
DragDropableRadTextBox_MouseDown(sender
As
System.
Object
, e
As
System.Windows.Forms.MouseEventArgs)
Dim
TextBox
As
RadTextBox = TryCast(
DirectCast
(sender, RadTextBoxElement).TextBoxItem.HostedControl.Parent, RadTextBox)
initialMousePos = e.Location
If
e.Button = System.Windows.Forms.MouseButtons.Left
AndAlso
selectionLength > 0
Then
current = TextBox
TextBox.SelectionStart = selectionStart
TextBox.SelectionLength = selectionLength
End
If
End
Sub
Private
Sub
DragDropableRadTextBox_DragDrop(sender
As
System.
Object
, e
As
System.Windows.Forms.DragEventArgs)
Dim
TextBox
As
RadTextBox = TryCast(
DirectCast
(sender, HostedTextBoxBase).Parent, RadTextBox)
If
current <> TextBox
Then
TextBox.Text += Convert.ToString(e.Data.GetData(DataFormats.Text))
selectedText =
String
.Empty
End
If
End
Sub
Please note that in this case the default dotNet Ole drag and drop functionality is used and it appears that it has some limitations. For example if you select text and release the mouse outside of the textbox, the text would not be stored (on MouseUp) and the drag and drop cannot be started. So in order this solution to work you should always release the mouse within the textbox when selecting. We cannot implement this in a different way since we do not know at which point the user wants to select text or wants to start a drag and drop operation.
Do not hesitate to contact us if you have other questions.
Regards,
Dimitar
Telerik
Thanks you for your explanation for the mouse release out of the control (which do not start the MouseUp event).
One solution would be to store the textbox on the MouseDown event and find a "Global" MouseUpEvent on Windows. So we can get back the textbox and then check the selected text lenght. But another global MouseDown event should be able to clear the textbox reference when the user click anywhere.
But a simple reference to my user about releasing the mouse over the control
Thanks for you support.
Could you just change "If current <> TextBox Then" by "If current IsNot TextBox Then" and remove "initialMousePos = e.Location" from your code sample ?
Thank you for writing back.
It is possible to detect mouse move/release at a global level using mouse hook. Please find attached the modified sample project, demonstrating how to stop the drag and drop operation when the mouse is released no matter over which control.
Please refer to the following useful links, related to capturing mouse events:
- http://stackoverflow.com/questions/804374/capturing-mouse-events-from-every-component-on-c-sharp-winform
- http://www.codeproject.com/Articles/7294/Processing-Global-Mouse-and-Keyboard-Hooks-in-C
- http://www.codeproject.com/Articles/5038/Using-Hooks-from-C
Regards,
Desislava
Telerik
Big up for your sample and the mouse detector class.
It's has solved the last know bug for our DragDropableRadTextBox.
The links were also very interesting.