WPF discussions 090626

Emails from our MS internal discussions. Lots a great tips.


Subject: Advise for running WPF apps over Citrix

Answer:
All versions of WPF since WPF 3.5 SP1 have remoted (both with Remote Desktop and Terminal Server) using Bitmap Remoting.

Bitmap remoting works as follows:

  • The application is rendered on the server using WPF’s software rasterizer
  • As the application runs, the server keeps track of which regions of the application’s window are newly dirty and need to be updated
  • When a region needs to be updated, the server creates a compressed bitmap of just the dirty region and sends that to the client
  • Once the client has drawn that bitmap to the appropriate place on its own window, the client window is up-to-date

Given how this remoting mechanism works, performance can be maximized in several ways:

  • Dirty regions should be kept as small as possible so the least amount of data is sent over the wire
  • Ambient animations should be turned off
    • For instance, setting a window background to an animating gradient would cause the entire window to be invalidated / redrawn every frame
  • The system does not optimize away occluded parts of the application
    • For instance, an animation that is completely hidden behind some other opaque element will still cause dirty region invalidation / bitmap generation to occur. Remove these from your application.
  • Dirty regions should be created as infrequently as possible
    • Turn off as many animations as possible
    • For those animations that can’t be eliminated completely, lower the animation framerate using the DesiredFramerate property
  • Dirty Region Bitmaps should be as simple as possible to maximize their compression
    • Application running over TS should favor solid colors over gradients or other exotic fills (unnecessary images, etc), especially for application pieces that will be redrawn frequently
  • Avoid operations that are especially slow when rendered in software
    • BitmapEffects / Effects / ShaderEffects, especially blurs and drop shadows with large radii, are quite slow in software
    • 3D – the 3D software rasterizer is substantially slower than rendering in hardware

Subject: Is there any support in WPF for “bottom-up” bitmaps?
I’m using BitmapSource.Create with an unmanaged memory buffer. The buffer comes from a Win32 DIBSection with a +ve height, which indicates a bottom-up DIB.

Answer:
Wrap it in a TransformedBitmap.
return new TransformedBitmap(bmp, new ScaleTransform(1,-1));

[extra tip]
Note that I think each call to CopyPixels() on the TransformedBitmap will run the scale transformation again. You can avoid this by caching the result in a CachedBitmap and using the CB instead


Subject: Getting DependencyProperty value from WinDBG
I have a dump of a WPF process and am trying to get the value of a DependencyProperty of UIElement.  Does anybody know how this can be done?

Answer:
1. Pull out the value of _packedData.
2. _packedData & 0x0000FFFF will give you the GlobalIndex.
3. Go to the DependencyObject on which you want to query the property and get access to the _effectiveValues array.
4. Go through the EffectiveValueEntry objects, looking at the _propertyIndex field until it matches the index you calculated in step 2 (the array should be sorted by property index).
5. _value is the value of the property on that DependencyObject.


Subject:   Difference between nulll and x:Null for brushes

I know there is a difference but I can’t remember. I think it had something to do with hit testing (but I can’t remember for sure).

Answer:
No difference. You're probably thinking of null (No hit test) versus Transparent (Can be hit).


Subject: Disable auto-word selection in FlowDocumentViewer
How can I make FlowDocumentViewer select character by character when I use the mouse?

Answer:
For FlowDocumentPageViewer, you can use flowDocumentPageViewer.SetValue(TextBoxBase.AutoWordSelectionProperty, false). FlowDocumentScrollViewer doesn’t auto-select words by default.

Internally, the selection code shared by text boxes and FlowDocument viewers relies on TextBoxBase.AutoWordSelectionProperty. We don’t currently expose the property on anything other than TextBoxBase.


Subject: Blend units.
Any reason why Blend3 outputs font size in WPF “units” and not the actual pt value. If I change the FontSize on a TextBlock to “11pt”, 14.667 is written out.

Answer:
Blend 2 always displayed text units in pixels. This was confusing to most designers who are used to thinking of fonts in terms of points. In Blend 3 we added an option where you can choose whether you want points or pixels as your display in the Property panel. This is under the Units tab in the Options dialog.

In terms of the XAML output, we had wanted to output the same units as shown in the UI but Silverlight does not support the pt syntax in XAML so we decided (for cost and consistency reasons) to just leave it as pixels in the XAML for V3. It is something for us to consider improving in the future though.


Subject: Disable IME on TextBox
Is there a setting to disable using IME on a textbox, or some other means of not allowing a user to use it?

Answer:
<TextBox InputMethod.IsInputMethodEnabled=”false” />


Subject: DateTime property in the Properties editor of Blend
I have a question regarding how Blend handles a control property which is of type System.DateTime.  I am trying to understand how the property editor would interpret a string such as 20/05/2001. Would it take into account the regional settings of the computer or is it tied up with the implementation of the control itself?

Answer:
Blend will use a text editor to read and display DateTimes, and will parse input based on the locale settings of your machine. In xaml, it is always stored in an invariant format(year-month-day).


Subject:   (summarized) issue w/ WPF not matching GDI on how a custom font is rendered

Answer:
There is no expectation that WPF font rasterization will match GDI\GDI+ rasterization. For example if the font does not have italic or bold variants GDI will emulate bold and italic WPF will not.


Subject: DPI interop issues...

I have a drag/drop gesture that draws a drag/drop feedback in a transparent WPF window. The problem is in tracking the mouse position I had to use interop to Win32.GetCursorPos and that works, when the operating system is in 96 DPI mode.  But when you change the OS DPI to something else, like 120 or 150 DPI then this doesn’t work because positioning the transparent WPF drag/drop feedback window requires WPF device independent coordinates (essentially 96 DPI) so I need to do a conversion

Answer:
Have you looked at Visual.PointFromScreen? It can be used to convert screen coordinates from APIs such as GetCursorPos into Device Independent Units


Subject: Game loops in WPF?
wondering how easy it would be to write a custom "game loop" within the WPF framework. By game loop, I mean pumping my own events on a custom Dispatcher so I can control the framerate of my app.

Answer:
You can write your own message pump. Just don't call Dispatcher.Run. You need to pump messages, and you need to call ComponentDispatcher.RaiseThreadMessage as appropriate. Use reflector to see what Dispatcher.PushFrame does.

Of course, this still may not give you what you want for a "game loop"...


Subject: Is there a way to prevent exception if DataContext is null?

This is just an example.

I have a Image which is Databind to some dynamic source (image source) and it works fine and it is all done in xaml. Can we provide some defaule image source incase DataContext becomes null?

Answer:

FallbackValue is your friend: https://msdn.microsoft.com/en-us/library/system.windows.data.bindingbase.fallbackvalue.aspx


Subject: Listening to selective ETW Events

I’m writing performance tests where we want to listen to the WClientUceNotifyPresent ETW event to calculate frame rates. However, I haven’t found provider flags to listen to it, along with a limited set of other events.

Answer:

With WPF 3.0-3.5 you unfortunately don’t have a lot of options. You should make sure that you’re using verbosity level 4 (as opposed to 5).

If you’re on CLR 4.0 we have much more granular flags so you’ll be able to turn on a flag specifically for Graphics related events which should help . If you have a recent drop (post Beta1) you should find our event manifest installed in \windows\microsoft.net\framework\v4.0\wpf\wpf-etw.man which lists the available flags. You will need either flag 1 `General` or flag 0x1000 `Graphics` depending on what drop you have.


Subject: Way to check if an UIElement is visible in ScrollViewer

Is there any way to check if an UI element is already showing in a scroll viewer?

Answer:
[Not right one, but works]
Use reflection to invoke ScrollViewer.IsInViewport method?

[Final]
I wouldn’t recommend this for production code.
Is there a reason you don’t want to call BringIntoView on elements that are already visible? All handlers of RequestBringIntoView I know of no-op on visible elements.