WPF discussion 090605

You know the drill: Raw/unedited WPF discussions from inside the mothership.


Subject: Accessibility tree, and collapsed elements

We have some UI that we’re collapsing (Visibility=Collapsed). However, even after it’s collapsed, it *seems* to be participating in the accessibility tree (shows up in UIspy). Is this the correct behaviour?

Answer:
It seems that this behavior is expected. However UI Elements that are collapsed should have the IsOffScreen property set to true. You could probably filter on that flag.


Subject: Blur the focus of a window

With WPF, how can you blur (lose focus) a window?

Answer1:
There are essentially 3 types of focus, which type do you want to blur? There are:

· Logical focus. This is essentially a way of marking which IInputElement in a given scope should receive keyboard focus if that scope gains keyboard focus. Within elements that are marked as a focus scope, there will be 0 or 1 logically-focused child elements. A focus scope is determined by FocusManager.SetIsFocusScope/FocusManager.GetIsFocusScope, and logical focus can be cleared by using FocusManager.SetFocusedElement on the focus scope to null.

· Keyboard focus. This is similar to Win32 focus; only one IInputElement on the thread with Win32 focus can be the Keyboard.FocusedElement. In 3.0/3.5/3.5 SP1, the only way I know of to clear WPF keyboard focus also involves clearing Win32 focus, by calling ::SetFocus(NULL) from user32. In WPF 4.0 there is a new method coming along, Keyboard.ClearFocus(), which will clear only the WPF keyboard focus.

· Standard Win32 focus. WPF keyboard focus is typically kept in-sync with Win32 focus (in that the focused HWND typically contains the Keyboard.FocusedElement), so doing operations which affect HWND focus will generally affect the Keyboard.FocusedElement.

Answer2:

Of course, you can always make an element lose focus by focusing another element, too. Calling Keyboard.Focus on some other element should result in PreviewLostKeyboardFocus/LostKeyboardFocus being raised on the element losing keyboard focus. Similarly, calling FocusManager.SetFocusedElement to some other element in the focus scope should result in PreviewLostFocus/LostFocus being raised on the element losing logical focus.

Confusingly, perhaps, calling Keyboard.Focus(null) will not clear keyboard focus, but will instead focus the active PresentationSource's root visual. This can result in Keyboard.Focus(null) actually focusing another element, and not clearing focus.


Subject: How do I change properties on the Navigation Bar in a WPF Frame?

I'm working on a page based WPF application, and I want to change the size of the navigation bar in the Frame hosting my pages. I set NavigationUIVisibility="Visible" in order to see the navigation bar, now how do I change properties on the navigation bar like it's size?

Answer:
The built-in navigation UI is not directly customizable. You’ll have to replace the entire ControlTemplate of Frame, possibly using the built-in one as a base. This is easy with Blend. Some resources:
https://windowsclient.net/downloads/folders/wpfsamples/entry5121.aspx
https://social.msdn.microsoft.com/Forums/en-US/wpf/thread/c98f9b2a-a910-45cd-acdc-fa5b222b7460/


Subject: Scroll issue with hosting a winform within WPF

I am having an issue trying to scroll a winform control hosted within WPF. I have a view (WPF UserControl) that has 3 elements. A checkbox, a hosted winform control (gray window below) and a combobox.

Answer:
Here’s an illustration of this technique for another source: https://blogs.msdn.com/ryanvog/archive/2009/01/20/clipping-legacy-content-hosted-inside-a-wpf-scrolling-region.aspx.


Subject: RE: Themes\Generic.xaml

Answer:
Only resources that are referenced with StaticResource from within the same resource dictionary (i.e. within Generic.xaml) can be strings. For everything else, you must use either a type key ({x:Type Foo}) or a ComponentResourceKey. Styles with no key specified default the key value to the TargetType of the Style.


Subject: Asynchronous Commands and Dispatcher

I have a command which executes a long-running operation using BackgroundWorker.  The command exposes a State property to which the UI can be bound to indicate that the operation is in progress or has finished.  The results of the command are bound to a TreeView.  Whenever an element is added to the results, the command does so by calling Dispatcher.BeginInvoke so that the element will be added to the results collection on the UI which causes the TreeView to be updated.  I call the BeginInvoke method with a priority of Background.  Once the command is finished executing, it updates its state to say it’s finished. 

The problem is that when there are hundreds of elements that have been added to the collection, the UI thread hasn’t finished processing all of those operations that have been queued on the Dispatcher by the time the command says it’s finished.  So the command says it is finished even though the UI thread is still busy processing all the queued operations. 

One solution is to have the Command update its State property by having the Dispatcher do it via the BeginInvoke call with the same priority.  That would cause the Dispatcher to update the Command’s state once all the other previously added operations have been processed.  But I’m not sure that’s the right approach; it feels very hacky.

Is there a better way to do this?

Answer:
Keep track of the last operation you BeginInvoke over to the UI thread from the worker thread. When the worker thread is done, before it updates the state property, have it call DispatcherOperation.Wait() to wait for the UI thread to finish.


Subject: RE: Blocking till message loop empty?

Answer:
Nope. Dispatcher.Invoke, when called on its own thread, will implicitly use Dispatcher.PushFrame.


Subject: RE: Bounding rectangle for objects on canvas

Answer:
GetDescendantBounds returns the bounds without applying any Visual properties like Clip, Transform, Offset, Effect…
Canvas.Left/Canvas.Top are mapped to Visual.VisualOffset and Visual.VisualTransform. To take the bounding box from what we call “inner coordinate space” (closest to children) to “outer coordinate space” (closest to parent) you have to apply all the transforms, clips, etc. Note that an effect might change your transformation too…

The easiest way to get the outer bounds is to call on the parent GetDescendantBounds as long as the parent does not have any “vector content” (think ink). For UIElements you provide “vector content” via OnRender, for DrawingVisual you call RenderOpen, etc. If the parent had any content, it would be included in the descendant bounds. The naming is a little unfortunate since it is not purely “descendant”. We originally had the functionality only consider descendants, but lots of people thought it was what it does now…


Subject: Disable script debugging for WebBrowser?

This option exists in the WinForms web browser, is there a way we can access this option in the WPF web browser also? We are having catastrophic issues with modal script debugger popups that make the browser too annoying to be useful.

Answer:

Get the native IWebBrowser2 and set the Silent property. See the Community section of the WebBrowser class reference (https://msdn.microsoft.com/en-us/library/system.windows.controls.webbrowser.aspx) for how to get IWebBrowser2.