Silverlight 4 and MouseLeave event inside an disabled UserControl - silverlight

I have a little problem with my RIA-enabled SL application.
THE BACKGROUND:
The relevant part looks like this:
When any data operation (i.e. load,
submit, login etc.) is in place, then
a BusyOverlay control (which I wrote)
disables RootVisual and provides a
visual effect. When the
operation is finished, then it sets
RootVisual.IsEnabled to whatever it
was before. It works just like
ChildWindow when it comes to
interaction with RootVisual (at least
as far as I can tell).
One of the elements in RootVisual (which itself is a UserControl) is a hiding menu. It is a border which contains the actual menu. It has two storyboards in Resources (which increase and decrease it's width - nothing fancy, they are as simple as you can imagine), and the border itself has MouseEnter and MouseLeave handled. The handlers start one of the storyboards, just one line of code. I don't provide any samples because there is nothing interesting going on, it would just bloat the post. If you think it is necessary, just tell me and I'll post the relevant XAML and C# code.
THE PROBLEM:
When the RootVisual is disabled, then the Border.MouseLeave event does not fire. When user clicks something in the menu that loads initial data, and then moves the mouse outside the menu, it does not hide. Is there any way to elegantly solve this problem? CaptureMouse is out of question (it requires mouse left button to be down). All I can think of is to publish an "OperationFinished" event in my data operation handling static class and handle it in the UserControl which is RootVisual, but I think it's ugly and doesn't fit in my architecture. Is there something I'm missing?
I'll be grateful for any solutions and suggestions.

Related

RichTextBox scroll to end not working when not visible

I have a WPF RichTextBox in my application that sits in Grid. It gets updated every second or two as it displays logs (though sometimes there are no logs for up to a minute depending on the load).
The grid is not always visible, as it sits in its own tab. If the user is on another tab, the logger is not visible.
My problem is that I want the RichTextBox to scroll to the end every time a new paragraph is added. It seemed simple as there is a 'ScrollToEnd' method on the RichTextBox control and so I call that method every time text is added to the control.
The problem is that that method only works if the control is visible, if the user is on another tab, the RichTextBox will not scroll to the end and it looks weird when you click on the tab with the logger and after a couple of seconds or longer it scrolls to the bottom when it should already be at the bottom.
Is there a way around this annoying "feature" of the control? I would like to ALWAYS have the RichTextBox be at the bottom unless the user is manually taking control of the scroll bar.
Thanks!
By default, the TabControl actually doesn't change its contents visibility, it removes them from the view completely when you change tabs and then "re-attachs" them when you navigate back to the previous tab.
That's why the Visibility change doesn't get fired. Instead, you should handle the Loaded event, which should get fired right before the view is re-rendered.
Is there a reason you cannot simply call ScrollToEnd in response to the text box becoming visible? That seems like the simplest approach. Did you try it and run into an issue?
Edit: If you are using a TabControl, each TabItem has an IsSelected property you can bind to from the ItemContainerStyle. You could probably scroll your text box in response to the tab becoming selected.
As a separate note: if you are planning to make a custom control for this, here are some things to consider.
I wrote an auto-scrolling version of a FlowDocumentScrollViewer. (I never needed a RichTextBox specifically, but they display similar content.) I can tell you that there are a lot of things to account for, such as knowing when and when not to auto-scroll based on what the user is currently doing.
For example:
If the user takes over the scrolling themselves via the scrollbar or mousewheel, you don't want the control to fight with them.
If they start selecting text, you don't want to scroll it away from them mid selection.
If they scroll to the bottom, you probably want it to start auto-scrolling again.
Also, determining what the user is doing to begin with can sometimes be a complex process on its own.

disable all input controls in a WPF Window

Is there a way to make an entire WPF Window inert after a button click?
The window is invoked via Window.ShowDialog() and after use, the window is no longer needed for interaction but I leave it open to remind the user of the inputs in TextBox's, ListBox's, and give visual feedback via OxyPlot and so on. I leave it to the user to close the window manually.
One solution is to disable all buttons but that's tedious and it still leaves TextBox's functioning. That's not optimal because for anything to be functioning creates the wrong impression that the Window remains for anything other than looking at. It would be better for every control to be non-functioning by a single setting.
I did it by putting a name on the WPF window code behind and then setting .IsEnabled false upon the appropriate button click. All buttons, combo boxes, text boxes, and even OxyPlot became inert at that point and most parts were greyed out.
Consider creating a dedicated boolean dependency property in your code-behind or viewmodel and binding IsEnabled of every TextBox to the property.

Disabling content behind an in-page dialog in WPF

I have some simple code for popping up a "dialog"-like thing over part of my application window. The idea is, the user must dismiss the dialog before continuing to work with that part of the page.
This works by hovering a large semi-transparent rectangle over the part of the page that is supposed to be disabled - which does a nice enough job of blocking clicks to the region. You see this sort of thing a lot in WPF and Web apps, I think.
The problem I have is, the user can still reach all those juicy blocked controls by tabbing to them using the keyboard. "No problem", I hear you say, "just set the IsEnabled on the panel to false, thereby blocking keyboard access".
Unfortunately, disabling the controls:
Doesn't look very nice
Tends to have unintended consequences with custom styles and bindings further down the tree
So, is there a better way to disable a part of the page, without setting the "IsEnabled" property, such that it doesn't change the visual appearance of any of the controls?
Thanks,
Mark
Can you put your "dialog" XAML in a popup window? Then, call ShowDialog() on the window to make it a modal window? If you don't want your popup to look like a standard window, you could always syle it to remove borders, etc.
I solved this by subscribing to the PreviewGotKeyboardFocus event, from the parent element in the tree, and then handling the event such that focus never gets passed to the children.
Also, I had to explicitly remove focus from the "disabled" controls as well, of course.

WPF custom panel control doesn't respond to mouse events

I've created a custom panel control and would like to have it respond to a mouse move event, however, when I add an event handler like so:
Private Sub FloatingPanel_MouseMove(ByVal sender As Object,
ByVal e As MouseEventArgs) Handles Me.MouseMove
End Sub
It only responds when I move the mouse over one of the child controls within the panel. I need to have it respond whenever I move the mouse anywhere inside the custom panel.
Update:
I found the following question which gave me a clue:
WPF - how to best implement a panel with draggable/zoomable children?
I can get mouse events on the
GraphCanvas itself only if it has a
background at the point
This led me to simply set the background which appears to have resolved the issue... My question now is, why? Why should I have to set the background in order to receive a mousemove event?
Update 2: The following code is what ultimately solved the problem (See Kent's answer below).
Protected Overrides Function HitTestCore(ByVal hitTestParameters As System.Windows.Media.PointHitTestParameters) As System.Windows.Media.HitTestResult
Return New PointHitTestResult(Me, hitTestParameters.HitPoint)
End Function
Thank you,
Matt
For the purposes of hit testing, WPF's default hit testing logic has two modes of transparency. One is transparent both visually and to hit testing (#00000000 or by not setting a background at all), the other is transparent only visually and does not preclude hit testing (##00ffffff). You want the latter.
I believe you could also override UIElement.HitTestCore in your custom Panel such that there is no dependency on having the background set.
I actually suspected this might have been the issue here; If the background of a control is null and there is no other subcomponent there your mouse is not moving across the control but accross the control behind it, so it makes sense that you do not get a mouse event from that (it is not very expected though because the bounds of the control may envelope the area).

What can act as a tab stop in silverlight?

I am working on a silverlight application with a significant number of invisible tab stops.
I am currently busy trying to track them all down and eliminate them.
I am aware that any control that inherits from System.Windows.Controls.Control can take focus and yet I still can't identify where the focus is be going for much of the time when I press tab to move round the UI.
So, my questions are:
Will everything that acts as a tab-stop also take focus (and visa versa)?
What, apart from anything that inherits from Control, can act as a tab-stop?
There is little point in something being a tab-stop if doesn't "also take focus". However not everything that can take focus need be a tab-stop, for example, a control may take the focus when clicked on by the mouse but not via the tab key.
In Silverlight there is nothing that can act as a tab stop that is not also a Control.
The Control class has a IsTabStop property which by default is true. If you have been building your own controls its up to you to build visual states to indicate that the control has the focus. If your control doesn't need the focus for any reason then clear its IsTabStop property early in its constructor.

Resources