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 SubThank 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 RadTextBoxPrivate 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 IfEnd SubPrivate 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 IfEnd SubPlease 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.

