How to detect a drop, regardless of where it occurred? - wpf

I am creating a WPF application with a drag and drop functionality.
When a drag is initiated, the colors of the rectangles in my window will change from white to green or red to indicate which ones are valid drop targets.
I want to revert the colors of the rectangles back to white whenever a drop was performed, regardless of where the drop occured.
I already managed to revert the colors back when the drop occured on the drop targets. But now I can't find a way to do the same thing when the drop is performed elsewhere.
I've tried something like this, but no luck for me:
Private Sub Meh(sender As Object, e As QueryContinueDragEventArgs) Handles DragSource.QueryContinueDrag()
If e.Action = DragAction.Cancel Or e.Action = DragAction.Drop Then
For Each R as Rectangle In Rectangles.Children
R.Fill = Brushes.White
Next
End If
End Sub
I even made a handler of the MouseUp event of the window to do it. Still no good.
Can anybody help me out here?

Related

Stopping an Unloaded event in WPF

I think this isn't the best way to go about doing this but this is the only way I can think of.
I have this WPF UserControl and it is called via a menu item (click on the menu and open the UserControl).
There are a number of things the user can do on the UserControl and I keep track of the changes made (via EF and a variable that is set to true if the user makes any changes).
Now comes the part where I know I'm doing wrongly. I want the UserControl to check if there have been changes or additions made.
I have placed this in the Unloaded event trigger.
Private Sub TheUserControl_Unloaded(sender As Object, e As RoutedEventArgs) Handles Me.Unloaded
If (changesMade) Then
Dim answer = MessageBox.Show("Changes have been.....", "Alert", MessageBoxButton.OKCancel)
If (answer = MessageBoxResult.OK) Then
If (saveChanges() = False) Then
'stop unloading???
End If
Else
MessageBox.Show("Discarding changes.")
End if
End if
End Sub
I realised that I have placed this in the wrong EventControl but I have no idea which Event Control to place it in.
So now I'm asking, where can I put this "check" to ensure that if the user navigates away from this page (by clicking on another item in the menu) they will be asked to save the changes made before the UserControl closes and if an error occurs in the saving, it would stop the UserControl from Unloading.
Thanks.

How can we handle the DataGridView improperly losing focus when used on a form that is accessed via Interop

We discovered a possible bug involving the DataGridView. The DataGridView has a property, StandardTab, that is set to False by default. This default setting means that the TAB key moves between cells within the grid. When it reaches the final cell in the grid, then the TAB key moves focus to the next control. This is the setting we are using in our project.
The DataGridView is connected to a binding source in our project, which may or may not be relevant.
When the DataGridView is on a form that is being displayed from a COM-based project (VB6, in our case), the grid control loses focus when the user tries to tab within the grid. If you hold down the tab key, focus cycles through other controls on the form until it returns to the grid. When it returns to the grid, the selected cell is the one that the user was tabbing to.
So, it is possible for the user to navigate through all the cells, via a detour through the rest of the controls on the form as they move from cell to cell. This does not make for happy users.
I did find an MSDN forum question that seems to describe this problem, but the only answer to it is not terribly helpful.
I could submit this as a bug on Microsoft Connect, but I doubt they are going to fix it. Is there a way to deal with this issue in code?
Further investigation of the following events/methods revealed a pattern:
Leave (on the control)
ProcessDialogKey (on the form and on the control)
ProcessDataGridViewKey (on the control)
The last two events turned out to be key to the problem.
When we tested in a 100% .NET project, we discovered that tabbing internally would execute the ProcessDataGridViewKey event to fire. When on the last cell, the ProcessDataGridView function was not executed, but the ProcessDialogKey function was executed.
When we tested in the Interop project, the events were exactly the same, but a Leave event on the control occurred before the ProcessDataGridViewKey function was executed. The bad scenario is unique in that the control will not have focus then ProcessDataGridViewKey function is executed.
Perhaps we can test for that and make focus come back to the control? It turns out that we can, and here is a subclassed control that handles it, yet still works fine in a 100% .NET project.
Public Class DataGridViewCustom : Inherits DataGridView
Protected Overrides Function ProcessDataGridViewKey(e As System.Windows.Forms.KeyEventArgs) As Boolean
' When the grid is hosted by a form that is being loaded through the Interop Forms Toolkit,
' the default behavior of using the TAB key to navigate between cells is broken
' (StandardTab = False). The tab key causes the grid control to lose focus before it has a
' chance to process the tab key in this event handler.
'
' This handler is not executed when the TAB key is supposed to make it lose focus (i.e. when
' StandardTab is True or when TABbing off the last cell within the grid). In those
' scenarios, the ProcessDialogKey event handler is executed, and there is no problem.
' Therefore, we can assume that if this event is being processed, and the grid does not have
' focus, we should put focus back on the control.
' The datagridview has different behavior for TAB and CTL-TAB, depending on how the StandardTab
' property is set. We don't have to worry about that becuase this method only executes when the
' focus is supposed to stay within the control. A different method is executed when the focus
' is supposed to leave the control.
If e.KeyCode = Keys.Tab AndAlso Not Me.Focused Then Me.Focus()
Return MyBase.ProcessDataGridViewKey(e)
End Function
End Class

Where do I find those WinForms controls?

I am looking for a WinForms control that, I believe, in the days of VB 6.0 (I can't remember if it was VB 6 or .NET 1.1) used to be called the ButtonImage or ImageButton or some such. Whatever it was called is not important.
What it used to look like and behave like is the important thing.
If you open Control Panel -> Add Remove Programs in Windows XP, the buttons on the left Change or Remove Programs, Add New Programs, etc. use tat control. I want a control that looks like that. It's a button with an image but stays pressed when it is selected.
Secondly, I am looking for a splitter. I see one in the Toolbox in Windows Forms apps, but when I try to change its size at runtime, it won't.
Do I have to use a SplitterContainer first or something?
You may make use of RadioButton control or CheckBox control.
Add the control and change the Appearance property of RadioButton to Button. Add a BackgroundImage to that.
Unfortunately this control doesn't exist in Windows Forms. You will probably find one in commercial control libraries, look for Outlook-type menus.
For the splitter, you have to use a SplitterContainer, which is two panels separated by a splitter. Then you add your controls on both splitters and will be able to move the splitter and everything.
For starters you can make the button use an image by tweaking the properties like so
Button1.Text = ""
Button1.Size = New Size(100, 100)
Button1.TextImageRelation = TextImageRelation.ImageAboveText
Button1.Image = My.Resources.Image1
That would make the button look like this
You could also swap out the image every time the user clicks with the buttons click event.
Make sure to replace image1 and image2 with the real images.
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
If Button1.Image = image1 Then
Button1.Image = image2
Else
Button1.Image = image1
End If
End Sub
You if you want the image to border and hover to be different try messing around with the button.FlatStyle = flat and the FlatAppearance property's.

Blacklight Expander problem while expanding programmatically

I am doing a silverlight project in Silverlight 4 and I included the BlackLight project in my project so that I could use their new controls, especialy the dockpanel and the autoexpander, which is causing me at the moment some little problems.
What I would like to do is to have several auto-expander that will expand or collapsed when I click on button. In my case more specifically, each auto-expander have a set of parameter to fill, which in turn will fill the other expander and the current one would collaps and the just filled one would expand.
The idea is simple, yet when I use a button which is on one of my expander, it only works once... It would expand/collapse the first time, then after that, nothing. I trace the code and it seems to go through just fine, but the property value won't change
Here is my code
Private Sub BtnExpand_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles BtnExpand.Click
ClientExpander.IsExpanded = False
ProjetExpander.IsExpanded = True
End Sub
Could it be a known bug, or must I reset some flags to make it work?
Edit : Forgot to mention, if it makes any difference, but the IsExpanded property seems to be a dependancy property.
Thanks.

Out of range error when closing pop-up

I have a Silverlight control that appears on top of another (picture a pop-up box). In this pop-up control, I have a scrollview (height = 250) with a stack panel (instance name = spMain, orientation = vertical) inside. Within the contents of the stack panel are several textboxes stacked on top of each other. When I tab from textbox to textbox, the scrollviewer automatically moves toward the bottom (I wrote code in an event handler that all textboxes are linked to that does that).
The problem I'm having is when I attempt to close out the pop-up control, I'm receiving an error stating that the value does not fall within the expected range.
if (sender is TextBox)
{
TextBox tb = (TextBox)sender;
try
{
// Code bombs out here when I attempt to close out the pop-up control
Point pt = tb.TransformToVisual(spMain).Transform(new Point());
if (pt.Y >= scrollViewerHeight - tb.ActualHeight)
{
svMain.UpdateLayout();
svMain.ScrollToVerticalOffset(scrollViewerHeight += pt.Y);
}
}
catch (ArgumentException aex)
{
// Don't want to eat the exception
string errorMessage = aex.Message;
System.Diagnostics.Debug.WriteLine(errorMessage);
}
}
I'm not surprised I'm getting the error, because it appears to make sense, but what I'm looking for is some sort of User Control Unloaded event or prevent the offending code from executing.
Does anyone have any ideas on how to go about this?
I think the problem lies with how you're closing the popup. Are you removing it from the visual tree or just setting its visibility to collapsed?
If (as I think your problem suggests) you're removing it from the visual tree entirely, you may be able to solve the immediate problem by collapsing the visibility of your text boxes first, and then removing the control. That assumes that your code above is being called as a result of a resize (or a potential resize) of the textboxes. Alternately, you could just empty them of content before you remove them also.
As for an Unloaded event, there isn't anything in the framework that'll do that for you. You could write a custom unload method for your control easily enough though, and just use that when you want to remove it.

Resources