So I have an objectlistview (actually a treelistview). I want to be able to drag an item from this onto a richtextbox, and have it insert a property of the dragged item (in this case Default_Heirarchy_ID)
The TreeListView's objectmodel is a List<T> of a class called SpecItem.
This is what I have so far:
public frmAutospecEditor(SpecItem siThis_, List<SpecItem> lstStock_)
{
InitializeComponent();
txtFormula.DragEnter += new DragEventHandler(txtFormula_DragEnter);
txtFormula.DragDrop += new DragEventHandler(txtFormula_DragDrop);
...
}
void txtFormula_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Copy;
}
private void tlvSpecItem_ItemDrag(object sender, ItemDragEventArgs e)
{
int intID = ((SpecItem)tlvSpecItem.GetItem(tlvSpecItem.SelectedIndex).RowObject).Default_Heirarchy_ID ??0;
DoDragDrop(intID, DragDropEffects.Copy);
}
private void txtFormula_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)
{
object objID = e.Data.GetData(typeof(String));
//this is where it goes wrong - no matter what I try to do with this, it
//always returns either null, or the text displayed for that item in the TreeListView,
//NOT the ID as I want it to.
string strID = (string)objID;
txtFormula.Text = strID;
}
Where am I going wrong?
Cheers
The Drag is the control you want to take data from (your OLV).
The Drop is the destination control (your textbox). So:
Set the IsSimpleDragSource property of your OLV to true.
In the textbox set AllowDrop property to true. Then handle the DragEnter event of your textbox and use the DragEventArgs param.
Handle the ModelDropped event:
private void yourOlv_ModelDropped(object sender, ModelDropEventArgs e)
{
// If they didn't drop on anything, then don't do anything
if (e.TargetModel == null) return;
// Use the dropped data:
// ((SpecItem)e.TargetModel)
// foreach (SpecItem si in e.SourceModels) ...
// e.RefreshObjects();
}
Read more: http://objectlistview.sourceforge.net/cs/dragdrop.html#ixzz1lEt7LoGr
Related
Yesterday I try to implement a new listview that support sub-item edit, my solution is to show a textbox when double click the sub-item. The key code as following:
protected override void OnDoubleClick(EventArgs e)
{
Point pt = this.PointToClient(Cursor.Position);
ListViewItem curItem;
int subItemIndex = GetSubItemAt(pt.X, pt.Y, out curItem);
DoubleClickEventArgs args = new DoubleClickEventArgs(subItemIndex);
base.OnDoubleClick(args);
if (subItemIndex>=0 && !args.Cancel)
{
//StartEdit(...);
}
}
public void EndEdit(bool acceptChanges)
{
//validation
.................
.................
AfterSubItemEventArgs e = new AfterSubItemEventArgs(this.SelectedItems[0], m_editSubItemIndex, this.SelectedItems[0].SubItems[m_editSubItemIndex].Text, m_textbox.Text, false);
OnAfterSubItemEdit(e);
if (e.Cancel)
{
//....
}
else
{
//set new value
}
m_textbox.Visible = false;
m_editSubItemIndex = -1;
}
OnAfterSubItemEdit is a event that user can do some validations or other operations. I add a check in this method, if the new value exist, I will show a messagebox to user firstly, then hide the textbox. But now, the problem comes, when i move the mouse, the listview items can be selected, I don't how to solve this issue, I tried my best to find out the way, but failed. So, please help me!
Listview has a LabelEdit property; when you set it "true", then in an event handler you can call Listview.Items[x].BeginEdit(), and edit an item. As an example, you can handle ListView.DoubleClick event and call BeginEdit right there:
private void Form1_Load(object sender, System.EventArgs e)
{
listView1.LabelEdit = true;
}
private void listView1_DoubleClick(object sender, System.EventArgs e)
{
if(this.listView1.SelectedItems.Count==1)
{
this.listView1.SelectedItems[0].BeginEdit();
}
}
The problem is that your form still calls the DoubleClick event whether the value exists or not. Add appropriate condition before calling base DoubleClick in your code, i.e.:
if(!new value exists)
base.OnDoubleClick(args);
I've got a TreeView and Canvas in my WPF application. I'm trying to implement functionality whereby users can drag a TreeViewItem and a method should be called when the user drops on the canvas, passing the TreeViewItem header as a parameter to this method.
This is what I've done so far:
private void TreeViewItem_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.Source.GetType().Name.Equals("TreeViewItem"))
{
TreeViewItem item = (TreeViewItem)e.Source;
if (item != null)
{
DataObject dataObject = new DataObject();
dataObject.SetData(DataFormats.StringFormat, item.Header.ToString());
DragDrop.DoDragDrop(item, dataObject, DragDropEffects.Copy);
}
}
}
When I drag and drop to the canvas nothing happens. I am thus unsure of what I should do next. I feel that it's something really small, but I'm at a loss. How can I call the method and detect that the header has been dropped?
Any ideas?
You need to set AllowDrop to true on your target element and then handle DragOver and Drop events on the target element.
Example:
private void myElement_DragOver(object sender, DragEventArgs e)
{
if (!e.Data.GetDataPresent(typeof(MyDataType)))
{
e.Effects = DragDropEffects.None;
e.Handled = true;
}
}
private void myElement_Drop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(typeof(MyDataType)))
{
// do whatever you want do with the dropped element
MyDataType droppedThingie = e.Data.GetData(typeof(MyDataType)) as MyDataType;
}
}
am doing something very very simple.
I have a listbox whose events are set like this :
public Form1()
{
InitializeComponent();
this.listBox1.AllowDrop = true;
this.listBox1.DragEnter += new DragEventHandler(listBox1_DragEnter);
this.listBox1.DragDrop += new DragEventHandler(listBox1_DragDrop);
}
void listBox1_DragDrop(object sender, DragEventArgs e)
{
//code to add labelText to Items of ListBox
}
void listBox1_DragEnter(object sender, DragEventArgs e)
{
//set DragDropEffects;
}
now I have a label, code for which is as follows:
private void label1_MouseDown(object sender, MouseEventArgs e)
{
DoDragDrop((sender as Label).Text, DragDropEffects.Copy);
//this.label1.DoDragDrop((sender as Label).Text, DragDropEffects.Copy);
//used one of them at a time.
}
but nothing happens. listbox DragEnter event never fires up. in fact, drag never happens.
whenever i try to drag label (text), not allowed windows cursor appears, instead of 'DragDropEffects.Copy's cursor
Drag and Drop doesn't take place..
when I modify the listbox (and the associated code) to accept files to be dropped on it from any other window, that works perfectly.
so..am unable to perform drag from a control kept on the form to another control kept on the same form.
am I missing something? am running windows XP.
I went through this and through this
please help...
Your code does work actually.
You just have to set the right drag effects in your event handlers.
void listBox1_DragDrop(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Copy;
}
void listBox1_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Copy;
}
Check if ListBox.AllowDrop is set to TRUE or not
The following is an example of what you need, with all the code (adding it here for whoever finds this post).
#region Initial Values
//Constructor:
public Form1() {
InitializeComponent();
}
private void Form1_Load( object sender, EventArgs e ) {
InitialValues();
}
private void InitialValues() {
PrepareDragAndDrop();
}
#endregion Initial Values
#region Drag & Drop
private void PrepareDragAndDrop() {
//For the object that receives the other dragged element:
TheSamplListBox.AllowDrop = true;
TheSamplListBox.DragEnter += TheSamplListBox_DragEnter;
TheSamplListBox.DragLeave += TheSamplListBox_DragLeave;
TheSamplListBox.DragDrop += TheSamplListBox_DragDrop;
//For the object that will be dragged:
TheSampleLabel.MouseDown += ( sender, args ) => DoDragDrop( TheSampleLabel.Text, DragDropEffects.Copy );
}
private void TheSamplListBox_DragEnter( object theReceiver, DragEventArgs theEventData ) {
theEventData.Effect = DragDropEffects.Copy;
//Only the code above is strictly for the Drag & Drop. The following is for user feedback:
//You can use [TheSamplListBox] but this approach allows for multiple receivers of the same type:
var theReceiverListBox = (ListBox) theReceiver;
theReceiverListBox.BackColor = Color.LightSteelBlue;
}
private void TheSamplListBox_DragLeave( object theReceiver, EventArgs theEventData ) {
//No code here for the Drag & Drop. The following is for user feedback:
//You can use [TheSamplListBox] but this approach allows for multiple receivers of the same type:
var theReceiverListBox = (ListBox) theReceiver;
theReceiverListBox.BackColor = Color.White;
}
private void TheSamplListBox_DragDrop( object theReceiver, DragEventArgs theEventData ) {
//You can use [TheSamplListBox] but this approach allows for multiple receivers of the same type:
var theReceiverListBox = (ListBox) theReceiver;
//Get the data being dropped. In this case, a string:
var theStringBeingDropped = theEventData.Data.GetData( "System.String" );
//Add the string to the ListBox:
theReceiverListBox.Items.Add( theStringBeingDropped );
//Only the code above is strictly for the Drag & Drop. The following is for user feedback:
theReceiverListBox.BackColor = Color.White;
}
#endregion Drag & Drop
.
I have successfully created DragDrop functionality with user controls. Now I am trying to allow DragDrop functionality on some components such as ToolStripButton.
The base class, ToolStripItem, supports AllowDrop and the DragEnter/DragDrop events...
ToolStripButton hides these properties in the designer, but they are publicly accessable.
Originally I tried doing the following for each ToolStripButton:
button.AllowDrop = true;
button.DragEnter += new DragEventHandler(button_DragEnter);
button.DragDrop += new DragEventHandler(button_DragDrop);
However, the events were not ever firing. These buttons are contained within a MenuStrip, so I changed the MenuStrip.AllowDrop to true. Then I started getting DragEnter and DragDrop events, but the DragDrop event would fail due to a threading/invoke problem when accessing the Tag property of the ToolStripItem.
The ToolStripItems cannot be invoked upon. So I have tried invoking their container, the MenuStrip, with the same function. I am still getting a threading/invoke problem where the thread stops running as soon as I try to access the ToolStripItem.
Here is the code I'm using to retrieve the Tag information after invoke:
void button_DragDrop(object sender, DragEventArgs e)
{
menuStrip.Invoke(new DragEventHandler(MyDragFunction), new object[] { sender, e });
}
void MyDragFunction(object sender, DragEventArgs e)
{
int id = (int)((ToolStripButton)sender).Tag;
// Debugging never reaches this line
int dragId = (int)e.Data.GetData(DataFormatName, false);
MoveItem(id, dragId);
}
Is Drag and Drop to a component like a ToolStripItem simply not possible? Or am I doing something wrong?
Here is the code I got to work for me.
I assign the DragDrop properties in the form constructor since they are hidden in the designer.
foreach (object o in menuStrip.Items)
{
if (o is ToolStripButton)
{
ToolStripItem item = (ToolStripItem)o;
item.AllowDrop = true;
item.DragEnter += new DragEventHandler(item_DragEnter);
item.DragOver += new DragEventHandler(item_DragOver);
item.DragDrop += new DragEventHandler(item_DragDrop);
}
}
private void item_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormatName, false))
{
e.Effect = DragDropEffects.Move;
}
}
private void item_DragOver(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormatName, false))
{
e.Effect = DragDropEffects.Move;
}
}
private void item_DragDrop(object sender, DragEventArgs e)
{
int id = (int)e.Data.GetData(DataFormatName, false);
int category = Convert.ToInt32((sender as ToolStripButton).Tag);
MyFunction(category, id);
}
I have a dropdown list and radio button. If something is selected from the dropdown by the user, I want the radio button cleared. If the radio button is selected I want the selection of the dropdown cleared. Unfortunately, this creates events that cancel each other out. I tried using the sender as shown below to determine if the value was being changed by code or by the user, but that doesn't work. How do I make these events only work if the user is the source of the action?
private void rbBlank_Checked(object sender, RoutedEventArgs e)
{
// Verify source of event
if (sender is RadioButton)
{
// Display
comboBoxTitles.SelectedIndex = -1;
}
}
private void comboBoxTitles_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
// Verify source of event
if (sender is ComboBox)
{
// Display
rbBlank.IsChecked = false;
}
}
You won't be able to tell the difference between the two since the source will be the same instance for both occasions.
This doesn't answer the question directly but if you compare the SelectedIndex of comboBoxTitles in the SelectionChanged event handler, your problem should be solved
private void comboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (comboBoxTitles.SelectedIndex != -1)
{
rbBlank.IsChecked = false;
}
}
Try to compare if sender == instance of a control instead of is type of.
private void rbBlank_Checked(object sender, RoutedEventArgs e)
{
// Verify source of event
if (sender == rbBlank)
{
// Display
comboBoxTitles.SelectedIndex = -1;
}
}
private void comboBoxTitles_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
// Verify source of event
if (sender == comboBoxTitles)
{
// Display
rbBlank.IsChecked = false;
}
}
If you know the IDs of those controls, you can try something like this:
System.Web.UI.WebControls.WebControl webControl = (System.Web.UI.WebControls.WebControl) sender;
if( webControl.ID == <comboboxId>)
{
//Do something
}
I havent tried this, but I guess it might work.