Hi,
I've recently updated our main project to Q2 2014 (haven't got the chance to try SP1, but according to the changes list, I don't think it will fix the problem), and went through a full battery of tests, unfortunately this uncovered that the new version broke our drag and drop implementation.
We use CSLA objects to handle the persistence side, making the whole thing much too complicated to enable me posting some sample code (it will take days of work to cook it up), but I'll try to provide as much details as possible.
First of all, we were happily using the old events (not the DragDropManager events) to manage everything and it worked perfectly so far.
First issue was that Q2 2014 made the TreeViewDragDropExecutionMode default to "New" with the effect that the TreeView.PreviewDragEnded event didn't fire and our code to commit the data to the DB stopped being executed.
I could see on intellisense that the mode is now deprecated, and that I should use the DragDropManager events instead. And here the real trouble begun.
Note that iter.Current could be two different types of object, ReviewSet if it's a root item, AttributeSet otherwise. Both types are CSLA types of object, and have a series of fields that control their data persistence behaviour. The culprit here is the "IsDeleted" field: in both cases, the dragged object I fetch in this way has that field set to True, while all other objects have the expected "False" value.
Now, when dragging and dropping, the "Order" field that each object uses to control its position among its siblings (and they can have quite a few) will need to be updated for plenty of items in the treeview, so to maintain consistency; in order to do so, we could proceed in two ways:
Option one is the default CSLA version, where we would update the "order" value on all affected objects, and use the automatic behaviour to let the objects save their changes automatically. However, this is costly as each affected object will need to make its own round trip to the server to update itself, this sends back a new object that needs to be substituted in the client.
Option two, which we chose, is: change the appropriate values on the client objects, explicitly preventing them to auto-update. Send one command to the server, with the needed information to save the changes on server side (effectively repeating the same operations on SQL). We then listen for the command result, and if no error is returned we'll know that everything is fine. So far it worked, but now, since the "IsDeleted" field mysteriously decided to get the "True" value, the dragged object invariably goes back to the server and auto deletes itself. Not nice!
I can prevent this by telling the object to avoid the automatic update, but this won't reset the "IsDeleted" flag (as it's automatically handled by CSLA and it can't be changed) so my client list will contain objects that believe they are deleted, with unpredictable results that I don't want to discover the hard way.
Final diagnosis: this situation won't work. Even if the DragDropManager "official" way to handle events can work, the "IsDeleted" issue seems to be a game stopper. The questions therefore are:
- Do you have any idea of why this happens?
- Can we "unbind" the IsDeleted property so that when we drag an object it doesn't magically decide that it's deleted?
Temporary workaround: although deprecated, I've found that I can use the following
I.e., I'm still forcing the old system to work, which allows me to use the old routines and everything appears to work exactly as before (the dragged object does not get deleted!). However, this is playing with fire: someday, probably soon, you guys will decide to kill the old route and we'll find ourselves is real trouble.
In other words, I need some answers to the questions above.
In general, this is the second time that we get caught by scarcely or not at all documented breaking changes (the first one was about RadWindows), I write code myself, so I do understand the need to break some old things in order to move on, but I was expecting Telerik to be able to provide plenty of guidance on how to rewire stuff appropriately; in this case, I've found that your documentation is both lacking and misleading. This is the reason why I'm not using a support ticket: I'm guessing that this thread may be useful to other developers caught by the same kind of trouble.
Sorry if I sound harsh (I usually can only say good things about Telerik!).
Thanks and best wishes,
Sergio
I've recently updated our main project to Q2 2014 (haven't got the chance to try SP1, but according to the changes list, I don't think it will fix the problem), and went through a full battery of tests, unfortunately this uncovered that the new version broke our drag and drop implementation.
We use CSLA objects to handle the persistence side, making the whole thing much too complicated to enable me posting some sample code (it will take days of work to cook it up), but I'll try to provide as much details as possible.
First of all, we were happily using the old events (not the DragDropManager events) to manage everything and it worked perfectly so far.
First issue was that Q2 2014 made the TreeViewDragDropExecutionMode default to "New" with the effect that the TreeView.PreviewDragEnded event didn't fire and our code to commit the data to the DB stopped being executed.
I could see on intellisense that the mode is now deprecated, and that I should use the DragDropManager events instead. And here the real trouble begun.
- The documentation on the official help files is clearly outdated, it doesn't mention the deprecation and doesn't really make it clear how DragDropManager should be implemented (what's wrong with showing a full example?). Anyway, the demos do use it so I could get it to work.
- Unfortunately, the treeview is currently populated via binding and this apparently has some mysterious consequence on the built-in CSLA properties of the data object.
What I've found is that I can get access to the dragged object via
subscribing to DragDropManager.AddDragDropCompletedHandler(TreeView, TreeView_PreviewDragEnded, true) so to implement the data persistence into TreeView_PreviewDragEnded.
In this method I do the following to get access to the dragged data object:
TreeViewDragDropOptions options = DragDropPayloadManager.GetDataFromObject(e.Data, TreeViewDragDropOptions.Key)
as
TreeViewDragDropOptions;
AttributeSet draggedAttribute;
using
(IEnumerator<
object
> iter = options.DraggedItems.GetEnumerator())
{
iter.MoveNext();
rs = iter.Current
as
ReviewSet;
draggedAttribute = iter.Current
as
AttributeSet;
}
Now, when dragging and dropping, the "Order" field that each object uses to control its position among its siblings (and they can have quite a few) will need to be updated for plenty of items in the treeview, so to maintain consistency; in order to do so, we could proceed in two ways:
Option one is the default CSLA version, where we would update the "order" value on all affected objects, and use the automatic behaviour to let the objects save their changes automatically. However, this is costly as each affected object will need to make its own round trip to the server to update itself, this sends back a new object that needs to be substituted in the client.
Option two, which we chose, is: change the appropriate values on the client objects, explicitly preventing them to auto-update. Send one command to the server, with the needed information to save the changes on server side (effectively repeating the same operations on SQL). We then listen for the command result, and if no error is returned we'll know that everything is fine. So far it worked, but now, since the "IsDeleted" field mysteriously decided to get the "True" value, the dragged object invariably goes back to the server and auto deletes itself. Not nice!
I can prevent this by telling the object to avoid the automatic update, but this won't reset the "IsDeleted" flag (as it's automatically handled by CSLA and it can't be changed) so my client list will contain objects that believe they are deleted, with unpredictable results that I don't want to discover the hard way.
Final diagnosis: this situation won't work. Even if the DragDropManager "official" way to handle events can work, the "IsDeleted" issue seems to be a game stopper. The questions therefore are:
- Do you have any idea of why this happens?
- Can we "unbind" the IsDeleted property so that when we drag an object it doesn't magically decide that it's deleted?
Temporary workaround: although deprecated, I've found that I can use the following
private
void
RadTreeView_Loaded(
object
sender, RoutedEventArgs e)
{
Telerik.Windows.Controls.RadTreeView o2 = sender
as
Telerik.Windows.Controls.RadTreeView;
o2.PreviewDragEnded -= RadTreeView_PreviewDragEnded;
o2.PreviewDragEnded +=
new
RadTreeViewDragEndedEventHandler(RadTreeView_PreviewDragEnded);
TreeViewSettings.SetDragDropExecutionMode(o2, TreeViewDragDropExecutionMode.Legacy);
}
In other words, I need some answers to the questions above.
In general, this is the second time that we get caught by scarcely or not at all documented breaking changes (the first one was about RadWindows), I write code myself, so I do understand the need to break some old things in order to move on, but I was expecting Telerik to be able to provide plenty of guidance on how to rewire stuff appropriately; in this case, I've found that your documentation is both lacking and misleading. This is the reason why I'm not using a support ticket: I'm guessing that this thread may be useful to other developers caught by the same kind of trouble.
Sorry if I sound harsh (I usually can only say good things about Telerik!).
Thanks and best wishes,
Sergio