How to indicate allowable drage & drop targets? - wpf

I'm considering a UI design (using WPF), but I'm not sure how to implement a critical feature: The user will be assigning needs to resources. There are some rules about what assignments can be made, such as compatibility and availability. I would like to display a list of resources, and a list of needs. The user can make an assignment by dragging a need and dropping it onto an resource.
What I would like to do is show the user what possible assignments can be made by highlighting all assignable resources for a given need. This should be done when dragging any given need.
(I'm comfortable performing the highlight using a property on the resource ViewModels and triggers in XAML, and performing the drag & drop action.)
I don't see any events that are generic to dragging starting or stopping; they are either relevant to the source element, or to elements that are actively being dragged over. How can I evaluate a method to evaluate compatibility on every resource item when a drag is started?
EDIT:
As I am thinking about this more, it might be better to perform the highlighting function upon selection of the item rather than the start of dragging. As the items will typically be in ListViews or TreeViews, dragging will also cause the item to become selected. Additionally, the user will not have to initiate and hold a drag while considering their choices. As the list of targets may be long, the user may need to scroll to find one they want, which is not practical while dragging.
I can easily listen for the SelectionChanged events to evaluate the potential drop targets.

In WPF the drag drop services are well defined along with indicating applicability of which are valid draggable and droppable visuals for the dragged data.
http://msdn.microsoft.com/en-us/library/ms742859.aspx
EDIT
As per your requirement you need to indicate \ highlight \ focus valid droppable targets when drag starts.
For this the droppable visuals must register themselves for the type of data that is getting dragged. All drop targets will thus be notified when such data that they have registered for is getting dragged i.e. in DragDrop.DoDragDrop(..., <dragged data>, ...) call.
Now this is tricky, but you could use Clipboard services to hold the dragged data. The registered target visuals will be notified by the same Clipboard service when such data is added to the clipboard. You could have a command CanExecute() that constantly executes on the drag - drop view and checks the clipboard data is of the registered data type. If so it will set some view model based boolean property that has been attached against all those valid drop targets to true, that will highlight them thru the attached behavior.
In the case of falling back (drag or drop lost), the clipboard must be cleared.
But ofcourse this is easy said than done.... but worth a try.

While I have updated the question with my plans to pursue another UI approach (highlight upon selection), I have still been pondering what I perceive as a shortcoming in the WPF Drag & Drop services.
Suddenly I realized that the start of dragging calls my code in order to get the data being dragged. I can do whatever I want there, including the triggering of any additional UI effects! With this, it seems a little silly to expect such functionality in the DragDrop class...

Related

Custom Task pane and drag drop a tree view from pane to document (not the other way around)

I have used the demo here. All works well.
http://code.msdn.microsoft.com/Word-2010-Using-the-Drag-81bb5bff
However, when I try and swap out the listbox for a treeview, it just doenst want to play.
5 minutes to get the demo working and over 2 hours now trying to use the tree view instead. IT shouldnt be that hard surely?
Relating specifcally to the demo mentiond above and my modfiication from a listbox to a tree view:
There is a test on "e.Data.GetDataPresent" which determines the "effect" of the cursor/pointer as it is moving across the GUI - from the tree view in the task pane to over the document (With the effect being set in a ItemDrag event in this instance).
A "DragEnter" event is rasied when the cursor is then moved over the document (well a form overlaid on the document), If data is not found, the effect is set to "DragDropEffects.None".
This will mean when dropping the item on the document (via the invisibile overlaid form) the "DragDrop" event will not be raisd as "DropEffects.None" stops this.
The problem was surrounding my test of data bing present in the DragEventArgs.Data property.
The interesting thing, though, is the affect of "DragDropEffects" and its side effect on other events.

Drag from one user control and drop into another user control in Windows Phone 7

I am trying to create two user controls in Silverlight using the Windows Phone SDK 7.1. I would like to be able to drag from one control and drop into the other control (or at least receive the event that the drop has occurred).
I am able to give the appearance that the drag is moving the item by using a TranslateTransform. However, I would be interested in knowing whether this can be done by actually moving the element instead of transforming it. Can this be done?
Second, and probably more importantly, how do I get the second control to see the drop event? I've done lots of reading, and no luck with this so far.
FWIW, I am currently using a Grid in each control, but I would be open to changing to a Canvas or other control type.
I am not much aware of windows phone, but we can drag an object from one controller to another controller.(What i did in iOS)
Steps to be followed:
Both controllers should be in same window.
On ManipulationStarted(touches begin) drag the object or item from one controller, Move on another controller
On ManipulationEnded(touches ended) check the dragged object is within the second controller. if Yes, add the object to second controller.
I hope my answer helped you. If it's not useful sorry for that.

How to debug problems in XAML/WPF controls?

I'm trying to build a maintenance form in WPF, using Telerik's WPF controls. The idea is to have a grid and a form that are bound to the same collection. Changes to the grid should be immediately reflected in the form, and vice versa. An online example using Telerik's Silverlight controls is here.
My specific problem is that when I enter a new record (by clicking on the "Add" icon in the upper-right of the DataForm), the record is added to both the grid and to the form's collection, but it seems to break the synchronization. The new row in the grid stays highlighted, like the grid thinks it's not done being edited, and while changes to the current record in the form are reflected in the grid, changes to the current record in the grid are no longer being reflected in the form.
But my real problem is more general than that. WPF controls, like Telerik's, are heavily dependent on binding, and in having what they bind to support specific behaviors. In this case, the underlying record needs to support INotifyIEditableObject, so that when the user hits the Cancel button on the form, the EditCancel method on the record can be called. Which is then responsible for setting its properties back to what they had been, and then raising a NotifyPropertyChanged event, so that controls that are informed that they have been so set.
When I didn't have EditCancel working right, I would hit cancel on the form and the values in the grid would not be changed. My guess as to what is going on with the inserts is that something in either my collection or by records doesn't support whatever it is that makes this work. The grid doesn't know that the form has finished editing the record because either my record or the collection hasn't told it.
And here's the real question: how can I find out what these third-party controls are expecting? Telerik's RadGrid can be bound to pretty much anything that can be IEnumerated. But all this neat enhanced functionality depends upon being bound to collections that are very much more specific. I don't get errors, when I bind to a collection that lacks facilities that are needed for certain functions to work, I just get a control that doesn't work.
How can I tell, when working with someone else's control, for which I do not have source code, what functionality it requires, in the objects it binds to?
Your best bet would be to browse Telerik's documentation or ask on their support forums
If that doesn't work, I like to use Snoop for debugging WPF's Visual Tree and Reflector for looking through compiled libraries

Drop outside the control

I'm improving standart WPF TabControl. I want to add undocking functionality to it:
user drags the page just outside the TabControl and this page undocks in the window.
I want two events in this control - PageDragStart (raises when the page dragged outside) and PageDragEnd (raises when the page dropped outside)
I've got no problem with the first event.
But the second... OnDrop doesn't call, because the item dropped outside the tabcontol container. How can I know that it was dropped?
P.S. I want a universal control (so, undocking functionality shouldn't be connected and hardcoded with the window tabcontrol is placed or something like this)
Why use DoDragDrop at all? As I was reading your description, using Mouse.Capture by itself seemed the obvious solution:
Handle OnMouseLeftButtonDown on the tab and start capture
Handle OnMouseMove on the tab and update the cursor based on hit testing
Handle OnMouseLeftButtonUp on the tab, and stop the capture and make the appropriate change
The reasons you might ever consider DoDragDrop over simple mouse capture are:
Integration with Windows' OLE drag and drop so you can drag and drop between applications and technologies
Modal nature of DoDragDrop call (which actually seems to be more of a disadvantage to me)
Automated hit testing of targets
Standardized "drop operation" API to allow unrelated applications to handle copy vs move, etc.
You apparently don't need the OLE integration or multi-application support and you want to customize the hit testing, so it seems that DoDragDrop has no advantages over directly handling the mouse capture.
I solved the problem - in rather brutal and unsafe way. But for it's gonna work as the temporary solution.
Well, when I'm raising PageDragStart event, I call Mouse.Capture(this, CaptureMode.SubTree);
When the page is dropped somewhere - DoDragDrop throws different exceptions (COMException, NullReference (I couldn't find which object is null) and some others I don't remember).
I catch exception and call PageDragEnd event (if the property IsPageDraggingOut set to true).
As far as you can see this solution is really dirty and bad. But it works.
So, any other ideas (or some ideas how to work with Mouse.Capture properly)?

Complex .Net 2.0 Windows Forms control: where to start?

In order to make a convenient UI for an .Net 2.0 Winforms application I am working on, I have need for a control that I'm pretty sure goes beyond the "out of the box" behavior of any standard control. A mock-up of what I'm trying to achieve follows:
Mock up http://www.claware.com/images/temp/mockup.png
Essentially, this part of the application attempts to parse words into syllables from tribal languages (no dictionary to refer to; any and all unicode characters are possible.) By the time the user gets this far, he has already defined the vowels / consonants in his language and some other configuration. There is then an iterative process of (1) the application guesses which syllables exist in the language based on some rules, (2) the user refines the guesses, selecting the correct parsings or manually parsing a word, (3) the application "learns" from the user's feedback and makes smarter guesses, (4) repeat until the data is "good enough" to move on.
The control needs to present each word (the grey headers), then all the syllable break guesses (the white areas with dots separating the parts of words.) There is also a way to manually enter a parsing, which will display a text area and save button (at the bottom of the mockup.) When the user hovers over a guess, the background changes and "accept / reject" buttons appear. Clicking on the accept, or entering a manual parsing, removes the entire word from the list. Clicking the reject button removes just that item.
I'm by no means 100% sold on the formatting I have above, but I think you can get a general idea of the types of formatting and functional control I need. The control will also scroll vertically--there may be thousands of words initially.
My question for you experienced WinForms developers is: where to start? I would really, really like to stay within the .Net core framework and extend an existing control as opposed to a third-party control. (At the risk of starting a religious war: yes, I suffer from NIH-syndrome, but it's a conscious decision based on a lot of quick-fix solutions but long-term problems with 3rd party controls.) Where can I get the most "bang for my bucK" and the least reinventing the wheel? ListView? ListBox? ScrollableControl? Do I need to go all the way back to Control and paint everything manually? I appreciate any help that could be provided!
[Edit] Thanks everyone for the ideas. It seems like the most elegant solution for my purposes is to create a custom control consisting of a FlowLayoutPanel and a VScrollBar. The FlowLayoutPanel can contain instances of the custom controls used for each word. But the FlowLayoutPanel is virtual, i.e. it only contains those instances which are visible (and some "just out of scroll"). The VScrollBar events determine what needs to be loaded. A bit of code to write, but isn't too bad and seems to work well.
I would look at the TableLayoutPanel and FlowLayoutPanel controls. These will let you organize a series of controls with moderate ease in a vertical fashion. I would then create a UserControl that consists of a label and 2 buttons. The UserControl will expose properties like Text and events that are exposed for the button clicks.. For each entry in the list, you will create an instance of the UserControl, assign the text value, and handle the click events. The instance will be placed in the Table/Flow panel in the correct order. Both of those layout panels do allow for inserting items between other items so you can add/remove items from the list dynamically.
Edit:
Given the length of what you are trying to render, I would consider using the DataGridView and do some custom rendering to make it perform how you want it to work. Using the rendering events of the DGV you can merge columns, change background colors (like highlighting the dark gray lines), turn on/off the buttons, and handle changing the grid into edit mode for your rows to allow modification or inserting of new values. This method would easily handle large datasets and you could bind directly to them very easily.
Well, this certainly looks like a candidate for a custom component that you should be creating yourself. You can create this using standard .Net drawing commands along with a text-box, and a regular button control.
Now you want to find out where to start.
Create a Windows Forms Control Library project.
Drop in the textbox and the button control.
The panel drawing code should preferably be done by code. This can be done using the regular GDI+ commands.
Edit:
Here's another idea, and one that I've practically used in my own project with great success.
You could use a web-browser control in the app, and show your data as html. You could update the source of the web-browser control based on the input in the textbox, and clicking on the links in the web browser control will give you the event that you can trap to do some action. Your CSS will work.
I used this technique to build the 'desktop' in an app I made called 'Correct Accounting Software'. People loved the desktop so much that it is one of the best loved features of the app.
Here's how I would do it:
Create a custom control. In this custom control, have a ListBox atop a LinkButton, and when the LinkButton is clicked you can make it give way to a TextBox. The ListBoxes will have the top row unselectable... you can probably get the rest from there. When you get your list of words, fill a Scrollable of some kind with one control for each word:
(foreach String word in words){
myScrollable.add(new MyComponent(word));
}
From there, I'm not sure what you want to do with the boxes or the data, but that's my initial idea on the UI setup.
Use the WebBrowser control and generate the HTML markup into it using DocumentStream or DocumentText.

Resources