WPF Discussion, 090522

I hope you remember the drill; sorry that I missed last week, we had school


Subject: ItemsControl and Screen Reader

I have a WPF 4.0 ItemsControl as follows. The AutomationProperties.Name attached property is set to a string for the item containers. I expected the screen reader to read out the string when the item container get focus, however screen reader (I am using Narrator) actually read nothing. Could anyone give me some insights? Is it a bug of my code or the screen reader or WPF? Thanks a lot!

Answer:
Unfortunately ItemsControl does not support UIAutomation – it is primarily intended to be used as a base upon which multi item controls are built.
You could switch to any of the ItemsControl subclasses that do support UIAutomation (ListBox is probably your best bet)
Alternatively you can override OnCreateAutomationPeer in your own ItemsControl subclass and return an AutomationPeer implementation of your own. The ListBoxAutomationPeer and ListBoxItemAutomationPeer implementations are really small simple starting points.


Subject: Create hidden WPF window ... with an HWND

I am trying to create a WPF Window that’s initially hidden, do a bunch of initialization, then show the window. In my case the initialization requires access to the HWND that will be hosting the Window. But it appears to me that the HWND is not actually created by WPF until either I call either Window.Show() or Window.Visisibility=Visible. And doing so, of course, makes my app window visible but blank for awhile before my initialization is complete.

Answer:
Currently, the only good workaround here is to supply an initial window position that’s entirely off-screen, then move it into view once everything’s ready. That way the blankness/flicker can’t be seen. For our next release, we’ve added a method to the WindowInteropHelper class called EnsureHandle to cause the HWND to be created before the window is shown.


Subject: Rendering delay when first displaying cached images

I’m tracking down a perf issue with my WPF application. Basically I cache a BitmapImage:

this.cachedImage = new BitmapImage();

this.cachedImage.BeginInit();

this.cachedImage.CacheOption = BitmapCacheOption.OnLoad;

this.cachedImage.UriSource = new Uri("IMG_0726.JPG", UriKind.Relative);

this.cachedImage.EndInit();

Then later I go to show it with

this.imageElement.Source = this.cachedImage;

But with large images, there is still a significant delay before the image renders, of a second or two. The UI thread does not appear to be blocked during this delay, so I suspect some conversion is happening on the render thread.

Answer:

Answer 1
We take a hit downsampling to display size - if you set DecodePixelWidth/Height on your bitmap to your display size, does that make this issue go away?

Follow-up 1 --

Though I do see a significant delay when resizing by a large margin, so that could be part of it. I still see a (smaller) delay when displaying an image with DecodePixelWidth set to the display size.

Answer 2
Right – we use high-quality resampling down to w/in sqrt(2) of the display dimensions, so you have to double (or halve) the area to cause us to do the “good” resampling. 

As an alternative, if the image quality is acceptable to you, you can set RenderOptions.SetBitmapScalingMode on the element displaying the Bitmap to speed this up.

https://msdn.microsoft.com/en-us/library/system.windows.media.renderoptions.setbitmapscalingmode.aspx

Follow-up

Thanks for the tip! Resizing to any size is now basically instant and looks pretty good.


Subject: TranslateTransform+ScaleTransform wierdness (artifacts)

I am seeing a weird problem when I applied TranslateTransform+ScaleTransform on a group of elements. When I change the scale factor, there is this random/unexpected gap between elements where they should be near each other.

Answer:

While the UI thread uses double precision for layout/hit testing, the rendering thread that actually displays everything converts all values to single precision floating point for speed. I haven’t run the numbers to determine if you’re outside the threshold of precision, but I would suspect that given your symptoms you might be.


Subject: RE: when do property changed event delegates get hooked up?

<Skipped question>

Answer:

A1
Correct – setting the Filter property (on a view) will cause that view to refresh. Setting some other property, such as a property on the data item that the filter might read, does not cause the view to refresh. Nor does it cause the item to be “re-filtered”.

The doc says that setting Filter (or Sort or Group) causes a refresh (meaning an immediate refresh). It’s not meant to imply that you never need to call Refresh ever again.

A2

I would argue the most straight forward reading of that MSDN fragment is that Refresh happens automagically. I know (from experience) that this isn't true for Filters (and can't be true), but it is true for Sorting and Grouping iirc. I think making it more explicit (i.e. SETTING Filter will cause a refresh) couldn't hurt.

A3
It is not true for sorting and grouping. Like filter, it is true that adding/removing a SortDescription or GroupDescription causes an immediate refresh, but changing a property on a data item (such as one that participates in the sorting or grouping) does not cause a refresh, or even a “re-sort” or “re-group”.


Subject: Any easy way to save a FlowDocument into a rtf or htm file?

Answer:

You can use TextRange.Save() with DataFormats.Rtf. You can get the TextRange with:
new TextRange(flowDocument.ContentStart, flowDocument.ContentEnd);

Answer 2:
The RTF converter doesn’t know what to do with embedded UIElements, so embedded TextBlocks will be dropped.

Followup2: Need data binding; that is why textblocks.

Answer 3:
We’ve made Run.Text a DependencyProperty for v4, so if you can build off of netfx4 databinding is supported directly. Otherwise, for earlier version of the framework see https://fortes.com/2007/03/bindablerun/.

Follow-up3:
will TextRange.Save support save to html format in .net 4.0 ?

Answer 4:
Unfortunately TextRange.Save does not support html in any version.


Subject: async bindings

Are async bindings evaluated on a background thread? 
Answer:
Yes!


A Rob Relyea must read ( I will come back to WPF in .NET 4 this weekend ).
https://blogs.windowsclient.net/rob_relyea/archive/2009/05/19/xaml2009-and-system-xaml-dll-preview-in-net-fx-4-beta1.aspx


Subject: Crash in wpfgfx_v0300

We have a small application that makes extensive use of DoubleAnimations to constantly move things around the screen. The way the code is currently written the animations are created and destroyed on a regular basis. application sometimes crashes in wpfgfx_v0300.

Answer:
https://support.microsoft.com/kb/962231


Subject: creating animated gifs using WPF

Answer:
In Win7, WIC supports GIF metadata and you can do this in WPF natively.


Public Announcement from Eric Fabricant

Subject: Update available for the .NET Framework Assistant for Firefox

Included in the .NET Framework 3.5 SP1 is an extension for Mozilla Firefox that adds ClickOnce support and reports installed versions of the Framework to a web server. This initial release didn’t provide a means of servicing the extension out-of-band without depending on Mozilla and was installed as a machine level component which prevented users from uninstalling the extension. To remedy these issues the Update to .NET Framework 3.5 SP1 for the .NET Framework Assistant 1.0 for Firefox has been released, updating the extension to version 1.1.

Grab your copy today before Firefox 3.5 introduces changes that will break version 1.0 of the extension and render it disabled.

Note: This issue has already been addressed in Windows 7


Subject: RE: Creating image from browser

Can I use GetDrawing() to obtain a snapshot of the FrameworkElement returned from another AppDomain via the CLR AddIn model.  The HwndHost control looks like an instance of MS.Internal.Controls.AddInHost.  I’ve adapted the code below but I’m still receiving a blank image.  Is there something different about the CLR AddIn model that would prevent this from working?

Answer:

What’s blocking your attempt is this in AddInHost:

/// <summary>

/// GetDrawing - Returns the drawing content of this Visual.

/// </summary>

internal override DrawingGroup GetDrawing()

   {

// HwndHost.GetDrawing returns a bitmap by calling the PrintWindow win32 API.

// This logic fails for the WPF hosting WPF (HwndHost + HwndSource) scenario.

// It currently works this way: PrintWindow redirects to Paint; If it is WPF,

// it calls back into HwndTarget.DoPaint, which invalidates window region.

// However, mil repaints async. Mil might not start paint before print.

// That is why it prints black(bug 117011).

//

// In 3.5 we decide to override HwndHost behavior and return null for hosting WPF, which will print white.

// So we do not waste toner printing black.

// There are a couple of approaches we will investigate in the future release

// 1. API that prints other than PrintWindow (This enables all WPF hosting WPF scenario).

// 2. The host communicates with the add-in via contract, HwndHost GetDrawing calls HwndSource.RootVisual.GetDrawing.

// (This is add-in specific).

if (_addInHwndSourceWrapper != null)

       {

return null;

       }

else

        {

return base.GetDrawing();

       }

   }

So, you have to get to the add-in’s Visual in its AppDomain, and call GetDrawing() on it directly.