We have a Smart Client plugin that was created for XProtect 2022. But in later versions we have found the drag and drop no longer works. This was first seen in XProtect 2024R1, 2023R3 was fine.
Our plugin is a user control that we bring in on to a dockpanel hosted on the WorkSpaceViewItemWpfUserControl control. It used to allow drag and drop of cameras from the left on to it, but now we get a red X, but drag and drop on itself no longer works i.e. a control on our user control, can not drop within the control itself either.
The user control is known to work and reverting the smart client back to 2023R3 works fine, we also tried updating the Nuget of VideoOS.Platform to the latest versions, but this made no difference.
Any idea what we need to do to get dropping enabled on the control, drag over works and we can see the DragDrop.DoDragDrop(source, dragData, DragDropEffects.Move) being fired too.
There is unfortunately no support for drag-drop to your own controls and this is a change from older versions. Also seen in the reply here - https://developer.milestonesys.com/s/question/0D5bH00000Yy08CSAR/drag-and-drop-not-working-on-smart-client-2024-r1
I did see that post, although it isn’t quite the same thing. Whilst we would like to drag and drop cameras from the left on to our control (which is what we did previously), we can’t even drag and drop within our control i.e. one of our own controls, on to another of our own controls, within the same control. Is drag and drop not supported at all, is there no way around this and if not, why hasn’t this been documented as a breaking feature?
One of our engineers digged a bit deeper into the issue and turns out that both drag of camera from side panel to a plugin as well as drag of plugin content to plugin is still supported. There is, however, a few things that has to be adjusted compared to what we have previously advised:
- DragOver event should be handled in addition to the DragEnter, DragLeave and Drop events
- Each event handler must ensure to set e.Handled to true if the event has been handled
The following snippets shows how to implement this in a simple ViewItemWpfUserControl, but implementation is very similar for WinForms (although we incourage to always use WPF):
.xaml:
<Label Content="Start String Drag By Clicking this" Grid.Row="0" MouseDown="Label_MouseDown"/>
<Label x:Name="dropLabel" Content="This is the drop target" Grid.Row="1" AllowDrop="True" DragEnter="dropLabel_DragEnter" DragLeave="dropLabel_DragLeave" DragOver="dropLabel_DragOver" Drop="dropLabel_Drop" />
.xaml.cs:
private void dropLabel_DragEnter(object sender, System.Windows.DragEventArgs e)
{
HandleDragEvent(sender, e);
}
private void dropLabel_DragOver(object sender, System.Windows.DragEventArgs e)
{
HandleDragEvent(sender, e);
}
private void dropLabel_DragLeave(object sender, System.Windows.DragEventArgs e)
{
e.Effects = DragDropEffects.None;
e.Handled = true;
}
private void dropLabel_Drop(object sender, System.Windows.DragEventArgs e)
{
string[] szDragDataFormats = e.Data.GetFormats();
if (!(string.IsNullOrEmpty(szDragDataFormats[0])))
{
// only allow drop if the dragged item is a camera list or string
if (szDragDataFormats.Any(s => s == "VideoOS.RemoteClient.Application.DragDrop.DraggedDeviceIdList"))
{
List<Guid> myCameraList = (List<Guid>)e.Data.GetData(szDragDataFormats.FirstOrDefault(s => s == "VideoOS.RemoteClient.Application.DragDrop.DraggedDeviceIdList"));
// in case the user has dragged an entire camera group
// only use the first camera
dropLabel.Content = myCameraList[0].ToString();
e.Effects = DragDropEffects.None;
e.Handled = true;
}
else if (szDragDataFormats.Any(s => s == "System.String"))
{
var dropData = (string)e.Data.GetData(szDragDataFormats.FirstOrDefault(s => s == "System.String"));
dropLabel.Content = dropData;
e.Effects = DragDropEffects.None;
e.Handled = true;
}
}
}
private void HandleDragEvent(object sender, System.Windows.DragEventArgs e)
{
if (e.Data.GetFormats().Any(s => s == "System.String" || s == "VideoOS.RemoteClient.Application.DragDrop.DraggedDeviceIdList"))
{
// visualize dropping allowed
e.Effects = DragDropEffects.Copy;
e.Handled = true;
}
else
{
// // visualize dropping rejected
e.Effects = DragDropEffects.None;
e.Handled = true;
}
}
private void Label_MouseDown(object sender, MouseButtonEventArgs e)
{
DragDrop.DoDragDrop(sender as DependencyObject,
"My text string",
DragDropEffects.Copy | DragDropEffects.Move);
}
Hi Peter, thank you for the clarification and extra information. We will give this a go and see how we get on, although i am pretty sure we already do as suggested in our plugin. I will report back when had chance to test.
Hi Peter, We have tried doing as suggested but it still looks to be the same. The issue i think is when things are embedded within user controls. We have a plugin WPF window, which launches a user control in to a dockpanel on the Milestone ViewItem WPF. Within our usercontrol, we have a number of other user controls which we are trying to drag and drop. We have set things to be handled as suggested on DragEnter, DragOver and Drop, but this has made no difference.
Is there somewhere i can share a sample project with you if i put one together?
Regards,
Phill
Hi Phil. Feel free to upload the sample here on the forum. Be aware that we are entering the vacation period, so responses might be rather delayed.
Regards,
Peter