WPF discussions, 091101

As usual, raw, unedited, useful info from the Microsoft’s internal WPF discussions lists.


Subject: All keys don't work in a WPF window when it is calling from a WinForm project.
We had a big project developed in WinForm. Now I'm adding a new window to the project using WPF. The WPF window is now part of the project, i.e. it is not a separate project or dll. What happened now is any control that is supposed to accept keyboard inputs, such as textbox, does not respond to my keyboard input. The window only responds to mouse.

Answer:
You must use call the EnableModelessKeyboardInterop method for keyboard to work.


Subject: Precision on WPF animations
This question was from a partner. they have some synchronization issue between their own animation and WPF animation. The difference of ~0.2 can happen because WPF animation precision depends on rendering timing, doesn’t it ?

Answer: That's right - we do a number of things to sync with rendering.
Time only "changes" at the start of a render pass, which is scheduled differently based on a number of factors (Desktop Window Manager present and enabled? Monitor refresh rate, desired framerate for animations, etc), and then too the time chosen is actually "in the future" a bit because we're trying to produce a set of changes that will be correct when they hit the screen. To do this, we estimate the future presentation time for a given UI thread's render pass. My guess is that this is what they're seeing in this case


Subject:   Using Blend Behavior in Style?
Why am I getting an error when setting a Behavior in a style. Isn’t Blend Interaction an AttachedProperty?

Answer:
Blend’s behaviors are an attached property, but publicly they are not exposed as a DP- you can do attached properties that are not DP’s by having just the static GetProperty/SetProperty.
We use this syntax to keep the behavior syntax smaller- by not using a real DP here we were able to default the collection to having a value and remove 2 lines of XAML. If this were a real DP then you’d have to add the collection to the XAML as well:

<Button>

  <i:Interaction.Behaviors>

<i:BehaviorCollection>

      <s:SimpleBehavior/>

</i:BehaviorCollection>

  </i:Interaction.Behaviors>

</Button>

In addition behaviors cannot be used inside of styles; the core issue is that we intentionally made behaviors not sharable- you can’t apply the same behavior to multiple elements. The reason is that if you use the WPF animation API as an example that it adds a ton of complexity to make the types sharable and it really detracts from the level of simplicity that we were looking for in Behaviors.

In WPF, everything applied through a style is shared across each element that it’s applied to. To get around this in early prototypes I used a trick with Freezables and the CoerceValueCallback to clone the behaviors every time they’re applied to an element and are already applied to something else, but none of this is present in SL and it can lead to some unexpected runtime behavior.


Subject: Best Match for ICO in WPF?
Is there a built-in way in the WPF 4.0 imaging classes to get a “best match” for a multi-frame ICO?

Answer:
We don’t have any automatic selection logic. You can iterate over all of the frames and find the one you want based upon each frame’s properties. You should be able to get them all from a frame by doing frame.Decoder.Frames. Alternatively, you can just do BitmapDecoder.Create and read the frames that way rather than indirectly through BitmapFrame.Create.
Note: pre-Win7 WIC does not support Vista’s PNG icon frames. If you hit a PNG frame you will get an exception on Vista and XP.


Subject: Binding and Custom Type Descriptors
In WPF we’re binding an object that has a custom type descriptor and are wondering if there is a way to get around a couple issues:

1. Is there a way to get WPF to listen to these changes given that WPF does not appear to subscribe to change events via PropertyDescriptor.AddValueChanged?
It appears that WPF will bind to the properties offered through the type descriptor, but WPF does not monitor that type descriptor for value changes.    It does appear to listen to INotifyPropertyChanged events, but this is not that useful if we are extending and object with custom properties.

2. Is there a way to have WPF bypass ICustomTypeDescriptor.GetProperties() when setting up a binding? In this case, custom types may hide the thing we actually want to bind to, so it would be useful to force WPF not to use the custom descriptor during binding.

Answer:
1. WPF will listen to ValueChanged if the object doesn’t implement INotifyPropertyChanged. If both are available we only listen to INPC, to avoid duplicate notifications. There are objects that expose both – chiefly ADO.Net’s DataRowView – so it’s a real issue. If you have appropriate access, you can get the object to raise the PropertyChanged event with a property name for your custom property. But if it’s not your object (and its OnPropertyChanged method is private), you’re out of luck.

2. No. We actually call TypeDescriptor.GetProperties(item), which in turn calls ICTD.GetProperties, so it’s out of our hands. Usually people want the custom descriptor to override the native one; we don’t have any way to ask for the other way around. (I’m curious what your scenario is, though. This is the first time someone’s asked for this.)


Subject: Binding to dictionary with multiple indexers
If I add a second indexer to a collection class, it will no longer bind to WPF FrameworkElement such that its index path can be referenced.
The following works fine on regular collection, But I add a second indexer, or if the collection is keyed, the binding no longer works:

  Path=[0].

Answer:
Your two indexers have different signatures, probably something like

                public object this[int index] { …}

                public object this[string s] {…}

The property path is declared in XAML, where everything is a string. So when you say “Path=[0]”, WPF has to decide whether you mean the first indexer with argument (int)0, or the second indexer with argument (string)”0”. There’s nothing in the XAML to indicate which one you mean, so I think we choose the line of least resistance and pick the second indexer – it requires no type conversion.

At any rate, you can provide the missing guidance by saying

                Path=[(sys:Int32)0]

assuming you’ve previously declared

                xmlns:sys=”clr-namespace:System;assembly=mscorlib”

This says what you think it does: “use the indexer that takes an int argument”.


Subject: SketchFlow transitions between screens?
Is it possible to create transitions between screens in SketchFlow?

Answer:
It should be doing this by default. The default transition is a fade, if you right-click a navigation connection in the map, there are a few more to choose from “Transition Styles”.


Subject: RE: How to improve the text rendering of your .NET 4.0 WPF Applications

Answer:
Important caveat: Do not use TextFormattingMode=”Display” on text that is going to be scaled by a RenderTransform (or scaled in any way other than by changing the font size). It will end up blurry.

Some more recommendations: https://blogs.msdn.com/text/archive/2009/08/24/wpf-4-0-text-stack-improvements.aspx


Subject: RE: Partner's question about WPF-Image convert & Flash support

Answer:

There are external EMF->XAML converters:
https://www.wpf-graphics.com/Paste2Xaml.aspx
https://www.verydoc.com/emf2vector/emf-to-xps.html

Indeed, WPF does not provide any native flash rendering. I doubt we ever will. Some options:
1) Host a web browser. Yes this is HWND interop code, so there are some compromises: the infamous airspace issues being the most prominent.

2) For display only, you might look at a DirectShow filter, like: https://www.medialooks.com/products/directshow_filters/flash_source.html


Subject: Property increment value i nBlend
If you expose a numeric property on a type and it is available in the  property window you can change the value by dragging the cursor up, down, left and right.  Is there a way to tell Blend what the incremental value should be?

Answer:

Yes, you need to supply a design-time assembly that uses the NumberIncrementsAttribute.

public sealed class NumberIncrementsAttribute : Attribute, IIndexableAttribute

Name:

Microsoft.Windows.Design.PropertyEditing.NumberIncrementsAttribute

Assembly:

Microsoft.Windows.Design.Interaction, Version=4.0.0.0

https://blogs.msdn.com/unnir/archive/2009/03/22/writing-a-design-time-experience-for-a-silverlight-control.aspx


Subject: pack: registration?

I forget, how do you open a pack: URI?
I tried using WebRequest.Create, but that gave me an error saying that pack: wasn’t registered… Then I tried using PackUriHelper to cause it’s static cctor to run, to try and get the prefix registered… PackWebRequest isn’t constructable (from what I can see)…

Answer:

[Multiple interesting data points]

#1 System.Windows.Application has a static ctor where ResourceContainer package is added to PreloadedPackages so that downstream PackWebRequestFactory can find it. So you need to be running in the context of an Avalon application to get this.

#2 If you use PackUriHelper class, the “pack:” prefix gets registered with the System.Uri class and this helps in performing the correct parsing and construction of System.Uri objects for pack Uris.

The other registration is of the pack: scheme with WebRequest so that you can use WebRequest.Create method to return the PackWebRequest object. This can be done in your code. PackWebRequestFactory does not register it. You could use PackWebRequestFactory directly to get the PackWebRequest too –

PackWebRequest request = (PackWebRequest)((IWebRequestCreate)new PackWebRequestFactory()).Create(packUri);


Subject: RichTextBox viewable area

Is there any way to get the viewable area in a RichTextBox?

Answer:

TextPointer upperLeftCorner = rtb.GetPositionFromPoint(new Point(0, 0), true /* snapToText */); TextPointer lowerRightCorner = rtb.GetPositionFromPoint(new Point(rtb.ActualWidth, rtb.ActualHeight), true /* snapToText */);

You could refine this to get a tighter fit by looking at RichTextBox.ViewportWidth/ViewportHeight, to omit space for surrounding chrome like the possibly visible ScollViewer or Border. But for optimizing a property set on the viewable area first, including a small amount of extra content around the viewport is probably fine.


Subject: ValidatesOnDataErrors not working on bindings inside an ItemsControl.

I noticed that ValidatesOnDataErrors is not working on bindings inside an ItemsControl.ItemTemplate. I confirmed this problem has been fixed in Framework 4.0 but our target is 3.5.

Answer:

the workaround is to use the “long” form of ValidatesOnDataErrors:

<Binding.ValidationRules>

                <DataErrorValidationRule/>

</Binding.ValidationRules>

 


Happy coding!!