Welcome to MSDN Blogs Sign in | Join | Help

Quite often,  I run into the “RenderTargeBitmap gave me an empty image” or “RenderTargetBitmap did not render my visual”..  
Hint: this happens a lot to people putting stuff into StackPanels.

The problem is that renderTargetBitmap is working at the Visual layer to render the visual and to do the rendering, it looks at the local properties of the visual (as expected).
Layout happens at a different (higher) layer in the platform but often ‘parents’ to your visual will apply offsets or transforms to your visual to position it, since the parent is setting these properties on your actual visual, these properties will be picked up by RenderTargetBitmap logic.

The best (and simplest) workaround I have seen came from Adam Smith ( WPF team lead and reliable WPF know it all). It simply wraps the Visual into a VisualBrush that it then draws into a DrawingContext.

private static BitmapSource CaptureScreen(Visual target, double dpiX, double dpiY)
{
    if (target == null)
    {
        return null;
    }
    Rect bounds = VisualTreeHelper.GetDescendantBounds(target);
    RenderTargetBitmap rtb = new RenderTargetBitmap((int)(bounds.Width * dpiX / 96.0),
                                                    (int)(bounds.Height * dpiY / 96.0),
                                                    dpiX,
                                                    dpiY,
                                                    PixelFormats.Pbgra32);
    DrawingVisual dv = new DrawingVisual();
    using (DrawingContext ctx = dv.RenderOpen())
    {
        VisualBrush vb = new VisualBrush(target);
        ctx.DrawRectangle(vb, null, new Rect(new Point(), bounds.Size));
    }
    rtb.Render(dv);
    return rtb;
}

I like that workaround the best, and that is the one I use most of the time. 
I know other people who workaround this same issue by wrapping the visual they are going to RTB in a Border. This abstracts any transforms that were being applied by the original parent, and now RTB works well.  I obviously don’t like this one as much since it ‘imposes’ on my Visual Trees.  Still, it works, so it is a choice.
 

Here is a screenshot of a sample demonstrating the issue and the solutions:

image
 

The first column is the original images and buttons. They are all in a StackPanel.  The top 3 items in this panels are not wrapped inside a border, the latter 3 are wrapped in a border.

 

The second column, shows what you would get if you just use RenderTargetBitmap.  Notice that the button and second image are missing; the reason is cause the StackPanel is offsetting them and RTB is picking that up.   
Do notice that even with no special workaround, the ones wrapped in the border worked OK.

 

The third column shows all the items rendered with the workaround above. Note that it works for all items, including the ones that had border.

 

The source code for this small sample (including the workaround) is here.

While I am into RenderTargetBitmap, a reminder to look at this KB article (and or QFE).
In 3.5 SP1, we fixed a few leaks for RenderTargetBitmap, but there is still one open; it has to do with doing RenderTargetBitmap of a 3D scene that has VisualBrushes inside the scene.

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: http://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.

 

The June release of the WPF toolkit went live today, it now includes the charts imagethat come with the Silverlight toolkit.

David Anson has the scoop and a great sample on the charts

The other controls (Datagrid, VSM, and DatePicker) also include a few minor fixes (check the release notes).
 
There is not an update for the WPF ribbon; we are still hopingthe update to ribbon comes after (or around same time) as .NET4 beta2. 

Enjoy the charts and the new toolkit, please don’t forget to send feedback.

 

PS. – Congrats to David Anson for the release; he has been the biggest advocate for the charts making it into WPF. I am sure he put some ‘over-time’ given how much they are doing with the Silverlight control toolkit too.  Thanks David!

Last friday, we had the pleasure of delivering the last stop in the WPF for LOB tour: Chicago. ChicagoXamlized

 

The training was very lively, with lots of people from all over the mid-west, and a few people from other further places…  It was a lot of fun at a good location (despite a shaky start with a microphone, that only lasted 45 mins ).  Definitely a good way to finish the tour..

The content for Chicago is now posted:  Decks  and demos 

 

Thanks to all the Chicago attendees!!

 

And thanks to every one else who helped us with the tour.  This has been a lot of fun and very enlightening and inspiring to us.

 

 

.

Last week’s stop in the WPF for LOB tour was Phoenix.   PHXXAMLIXED

Great weather, a great audience, and good times.
Having been twice in Phoenix this month I have to say they have a really great .NET community. Congratulations and thanks for joining us for the training!!

Here are the decks and the demos.

Thanks again Phoenix!!   Next stop: Chicago; c u there on friday.

 

My guess is that most Americans know this, but I did not.  The picture is from a well known place in Phoenix, called Camelback mountain. 
Courtesy of Terry Stanley, a training attendee (and now a XAML expert).

Wintellect just posted a great 70 page white paper on codeplex about the “programming differences between WPF and Silverlight”.  

I have not dissected it yet, but from a quick scan it looks very useful.
I will be printing it and dissecting it on my flight to the next (and last) WPF for LOB Tour stop: Chicago.

Please share feedback on the paper.   Is it useful?? What is it missing?? Is it a fair assessment of the status on our continuum.

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:
http://windowsclient.net/downloads/folders/wpfsamples/entry5121.aspx
http://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: http://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 (http://msdn.microsoft.com/en-us/library/system.windows.controls.webbrowser.aspx) for how to get IWebBrowser2.

A while ago, I cracked open Silverlight3’s PlaneProjection (aka 3D perspective transform ) feature. Below you should find the basic intro plus all the advanced stuff that had not been documented when I tried to learn it. It is a long read, if you are already an expert, skip to the “3D scene” section to read the interesting details.

The post comes with this application that I used to learn and illustrate the points.  Source for the app is here.
Click on the Figures below to go to the respective page on the demo app. SL3 is required!  You might need to maximize your screen to see the demos. 

Introducing PlaneProjection
Silverlight3 introduces a new Projection property on UIElement.   The property is of type Projection (an abstract class).
In SL3, the only implementation of Projection class is PlaneProjection, which is an implementation of a 3D PerspectiveTransform. As of SL3 beta1, the implementation is software-based (so not hardware accelerated today).
The UIElement that is projected into this 3D scene is interactive even if projected. Both front and back are interactive.


PlaneProjection = Transforms + 3D scene

For me, it is easiest to think of PlaneProjection as a wrapper for a 3D scene and series of 3D Transforms that you can apply to a UIElement to get it to ‘project’ in 3D space.

The transforms that PlaneProjection applies to its UIElement are: 

  1. A TranslateTransform exposed via LocalOffsetX, LocalOffsetY, LocalOffsetZ in PlaneProjection.
  2. A set of RotateTransform   represented by the CenterOfRotationX, CenterOfRotationY and CenterOfRotationZ  and the RotationX, RotationY an RotationZ properties.
  3. A TranslateTransform(3D), exposed via GlobalOffsetX, GlobalOffsetY, GlobalOffsetZ

Before I get into these transforms, let’s cover the coordinate system.

Silverlight 3D coordinate system

  Print

This system is similar to what Silverlight uses in 2D:
+Y increases as you go down the vertical axis, 
+X increases as you go to the right.
+Z increases towards the viewer.

Note: WPF uses a different system, called Right hand system,  in WPF, the Y increases as you towards the top on the vertical axis. 

 

 

 

 


               Figure1. Coordinate System

 

RotateTransform
A RotateTransform rotates the object around an axis (X,Y,or Z). 
You specify the CenterOfRotation (which is normalized, 0 to 1, as a percentage of the actual object size) for the axis, and then you specify the angle in degrees for the Rotation.

 

imageOn Figure 2, you can see an Image of a duck rotated around the X Axis.  You first see the original, and then four rotations at 40, 80, 120, and 160 degrees. All of the rotations are the same for each row, but the second and third row have a different CenterOfRotationY property.

The second row has CenterOfRotationY = 0.1; it rotates near the top of the UIElement (10% from the top).  

The third row has CenterOfRotationY = 0.9;  so it rotates near the bottom of our UIElement.

While looking at Rotations of 120 and 160 degrees, notice that there is no back material to our object. Silverlight acts as if back was transparent, letting you see the front material but rotated since you are watching from the back.

                                                                                                                          

                                                                                                                             Figure 2. Rotate Transforms

You may wonder what happens if I stack two objects in say a Canvas, one on front of the other, like this:                                                                                                                                             
                                                                                                                                                      
<CanvasWidth="300"Height="300">
  <Canvas.Projection>
    <PlaneProjection
RotationX="120"/>
  </Canvas.Projection> 
  <Rectangle
Fill="Red"Width="100"Height="100"/>
  <Rectangle
Fill="Black"Width="100"Height="100"/>
</Canvas>

We have a Red rectangle, right behind a Black one?  What is the back material now if we rotate the Canvas to see the back?
The back material is still  the Black rectangle; it looks like Silverlight projects what is visible on the screen, so you get the back of the Black rectangle. 

Rotations can be negative numbers; a rotation of –50 degrees looks like a rotation of 310 degrees; however, if you are animating you will see these animate in opposite directions (and 310 flips a lot more )yet they end up at same spot. 

For the most part, that takes care of rotate transforms.  The only other thing to notice is that since we are transforming a 2D object on an Axis, the CenterOfRotationY affects RotationX,  and the CenterOfRotationX affects the RotationY.


Translate Transforms.
A TranslateTransform simply moves the object by an Offset vector. For example: an object at 1,1,1 with an offset of 50,74,-1 will end up at  51, 75, 0).   The units are Silverlight units relative to the screen; more on this below when we cover the 3D scene.

PlaneProjection exposes two translate transforms:  A GlobalOffset and a LocalOffset transform:

GlobalOffset transform
The GlobalOffset Transform moves the object relative to the screen’s axis. This means the X,Y,and Z offset are in  the coordinate system I showed above in Figure1. Think about it as a translation after the rotation has happened.  The object is rotated first, and then after that, the resulting, rotated object is simply moved or translated.  This model is similar to what we see in 2D space.


LocalOffset transform
The LocalOffset as a translate transform applied prior to the rotation.  We already established that the CenterOfRotation affects the rotation.  Consider what happens if we first translate the object and then rotate it around a specific CenterOfRotation,  since the translate transform does *not* change the CenterOfRotation, you end up rotating around the axis with the translation applied.   That is what a LocalOffset transform does.

Figure 4 on the right shows you what happens with a LocalOffset + Rotation combination applied. 

imageRow1 shows three images in a spot (marked by red border).  Each image has a different frame (or border) and a different rotation. Green has RotationY=50;  Yellow RotationY=130 (so 180-50).  The third image (black border) has no rotation at all.

Notice that since first row has not translate transforms, therefore the rotations are in-place (within the red border).

Row2 shows same images +rotations), but LocalOffsetX=250.   The image in the black frame shows where the image is located after the translation; it is 250 units to the right of the red border (on X axis). Notice that the rotation is not in place any more (not within the red borders). In this row, the center of Origin is 0.5, so the images at 50 and 130 rotations are at symmetrical distance from the center of the red border (which is our center of origin, at 0.5).  

Row3 has LocalOffsetX=250 and CenterOfOriginX=0.1.
Since 0.1 is < 0.5, our CenterOfRotation is to the left from the one on previous row; since the center of rotation is farther away from the actual image, our rotation is the widest here.  The yellow frame is furthest from the red border.  
                                                                                                                          Figure 4. LocalOffset Transforms

The fourth rotation has CenterOfOrigin=0.9, so this time we are moving our CenterOfOrigin closer to where the image was translated to, so our rotation is less wide than it was at both 0.5 and 0.1 . 

 

That should cover the transforms!   If you need to play more with this, try the sandbox from the demos page.

Now we get to the other half of PlaneProjection: a 3D scene. 

The 3D scene
A 3D scene usually consists of a Camera,  Lights, a mesh (the shape of your object) and a material (used to “paint” or “cover” your object ).  You need to know the Position of the camera (relative to the objects in the scene) and the FieldOfview angle.

Print 

Figure 5 shows the basic elements of a 3D camera placement. 
F == field of View (in degrees or radians)
D == distance (on Z plane) from the camera to the XY plane
H == ActualHeight of object in our XY plane

 

 

                                                                                                                         

                                                                                                                                          Figure 5.  Basic 3D scene

Those are the basics of a 3D scene, let’s now cover the Silverlight 3 specifics: 

FieldOfView == 57.0  degrees
At first, I was slightly concerned that I could not change field of view, but then I noticed that Silverlight does  not clip the 3D scene.  PlaneProjection works similar to RenderTransform where as you scale your UIElement, you can go over the UIElement’s render bounds (ActualHeight/ActualWidth) and the transform does not affect layout.  This means if your container does not clip, then field of view is irrelevant as you are seeing everything regardless.    


image
Figure 6 shows Field Of view and clipping interaction 

Row1: A Canvas with two rectangles inside it. The blue rectangles take half the canvas space and the red rectangle takes 1/3 of the Canvas space.

Row2: With a PlaneProjection with GlobalOffsetZ= 500,  the Canvas is a twice its original size. Notice there is no clipping.  This is default SL3 behavior, so field of view is fairly irrelevant as you are seeing the whole scene most of the time.

Row 3: Same PlaneProjection applied to original Canvas, but this time the border hosting the original Canvas is clipping at 300x120..  So you only see partial scene.   Again this is not default behavior but for those wanting to clip, you know it can be done. 

 

 

                                                                                                                                 Figure 6. GlobalOffsetZ = 500, 2x.

                                                                                                                                                                                                                                      

D = 999

The next thing on the scene is the distance from camera to xy plane.  The answer there is a weird 999. The number I am certain, the behavior I am still trying to grasp .  Let’s explain:

image

If D was distance to camera and it was 999, then  when you did a GlobalOffsetZ > 999, the object should  not be in the scene, but what SL 3D does is allow for Zindex to be > 999 and then it rotates (as if you were looking at the back I assume).

Figure 7 shows:
Row 1: Original object. Rectangle with a gradient. This is very small on purpose (since it is scaled a lot when we increase ZIndex).  

Row 2: Same object, but GlobalZIndex = 900.  [so 99 away from 999].
Still looking at the front of the rectangel.


Row 3: Same object, GlobalZindex = 1098 [so 99 over 999]. Notice that the we are looking at the back of the object.  It is the same size than 900.

Row 4:  Has two objects. 
First object = original + GlobalZIndex = 1899 (900 over 999), notice we are looking at the back of object but it is not scaled much. Second object  is Original object + GlobalZIndex = 99. It is same size as GlobalZIndex = 1899 and we are looking at the front.    
                                                                                                                              Figure 7. GlobalZIndex > 999 

If you are wondering why when you look at the API for PlaneProjection the default value for GlobalOffsetZ and LocalOffsetZ is 0 and I am saying the camera is at 999,   PlaneProjection applies the D = 999 is by moving the object before you get the scene, so the distance to the camera is there, but you don’t see it (or can’t change it) from the API.

What about H? why does it matter?
H is relevant because it tells you where the camera is in relation to the XY plane.  Not the distance to it, but where within that plane the camera is located. The short answer is that the camera is at the center. The long answer is that there is some scaling going on to make that happen. 

For sizing of our scene, the math would go along H = 2*D*tan (F/2); since both F(57) and D (999) are fixed, then H should also be fixed (1084), but of course our UIElement is not of that same size, so the object is  scaled and aspect ratio is maintained.

For the most part, you do not notice this scaling (nor should you care), but if needed you can use this knowledge to accomplish two things:

  1. Position the camera
  2. Create a 3D scene where multiple objects of different sizes appear to be in the same scene, with a common camera angle.

image

 

Figure 8.
Let’s go back to our earlier example where I showed you a clipped scene,  this time the canvas in the last row is 500x120 instead of 300x120. if you see it before changing GlobalOffSetZ, visually it all looks the same. 

When you animate GlobalOffsetZ, you notice the center of origin of the Projection is farther to the right ( at 250, which is the first third in the rectangle, so our rectangle would no longer clip, part of it is visible. 

[I removed the clip on the border so you could see the scene, but it is easy to see that some of the red rectangle is still fitting in the border that was clipping the whole rectangle earlier.

 

                                                                                                                                           Figure 8 – Canvas to position camera.

 

The example above is not that exciting or enlightening; you can accomplish some thing similar with a few transforms, so I am not proposing that you change the size of your containers to manipulate the camera, however the trick does come in handy when you have UIElements that are of different sizes but need to “integrate” into a 3D scene; and the UIElements need to be rotated separately.  If you are familiar with WPF, this would be like having multiple GeometryModels within a scene; you rotate these independently, but relative to a single camera and lights scene.

Since I explained earlier that camera is located relative to the “center” of each UIElement, there fore getting multiple objects of different sizes to have the camera in the exact same spot is not doable unless we workaround it, and the workaround is to apply a Canvas to wrap each of my UIElements, and size all wrapper canvases to the same size, this way as I rotate them and manipulate them, they all have same relative CenterOfOrigin.

imageFigure 9 demonstrates this trick.    
Row1 shows a canvas with rectangles in it. The rectangles have slightly different sizes.

Row2 shows the rectangles translated to GlobalOffsetZ = 500 (twice original size).
Notice that the “top” of the rectangles are not aligned (unless the height of the rectangle was the exact same prior to the transform). I used the redlines to demonstrate the differences after translation.

Row 3 translated the canvas instead of the rectangles, notice the top of the rectangles are aligned.

                                                                                              Figure 9. Using same size Canvas to align UIElements
                                                                                                                  
to get same Center of Origin.

OK that covers most of what I found out on Silverlight’s PlaneProjection. I do have a useful sandbox page for playing around with a lot of these concepts.

 

On the overall 3D API, I think it is quite simple, yet it lets you do a lot.    

The third stop in the “Windows Presentation Foundation for Line Of Business Tour” NYXamlized was  New York City, last Friday and Sat.

We had a great  crowd, mixed with WPF newbees and experts; this drove us to long training days with lots of questions on both sides of the spectrum. 


Thanks to the attendees for sticking it out!

The decks are here.  The demos are here.

Our last two stops are coming up quickly:
Phoenix (this weekend) and Chicago (next week).

Thanks again, New York ( and Philadelphia, and Boston, and New Jersey and any one else who came from out of town).

This week, I had the pleasure of presenting at the “Phoenix AZGroups Scott Guthrie event”  (with Scott and Glenn).

The deck that I presented is here. It includes a small section on some of the most relevant differences between WPF and Silverlight (3); any one wanting to know the differences, should check it out.  If you have a difference you would like me to add, please email me or add a comment here.

--
I have to thank all the people that attended the event and our hosts Scott Cate and Joseph Guadagno. I flew down thinking it was a ‘smaller event’ (maybe 300 people) and was incredibly surprised with what they put together; it felt like a one-day conference, with ~800 people registered, great food and location, and huge give aways ( netbooks, Flip HD cams, books, etc.. ). Very, very impressed, congrats to the usergroup on such a great event.  

PS --  I will come back to the sharing code between WPF and Silverlight topic; in preparation for the talk, I spoke to 8 companies (agencies, ISVs, enterprises, etc.) doing code sharing already; overall, they were positive.  it is not seamless, but it can definitely be done.  If you want to see the client continuum in action, check Telerik’s SalesDashboard; built with high % of shared code between WPF and Silverlight; it uses prism too].  they give out the source for it too. Nice!

I am late to this  but still wanted to share an “insider view” into the status of “WPF 4” in the recently released .NET Framework 4 and VS 2010  beta1.


Status of the run-time (on the public beta 1).
The WPF team cranked hard until last minute on 3.5 SP1 so they have been playing catch-up to .NET 4 and VS2010.  The beta does not really do justice to the progress the team is making towards RTM. In a few cases, the team ‘compromised’ not shipping the feature in beta1 to optimize for the RTM schedule (preparing a beta does take integration work and testing, plus they had to put the longer/harder features up-front to decrease ship risks). 
Beta2 appears to be in good shape for you to preview and share feedback still before .NET 4 RTMs.  

For those looking into beta1, I would say the two areas where we need feedback will be:

  • The new XAML stuff (in particular we want to make sure we do not break you)
  • The tools ( Cider designer);  I would love to hear what people think of the new features. 

Want to learn more about beta1. Here is a bit of the action:

  • Video Interview with Ian Ellison Taylor WPF and Silverlight GM, and Kevin Gjerstad, WPF Group Program Manager.  It pretty much discusses what is in and out (for beta1 and RTM).
  • Rob Relyea recorded a video on the XAML enhancements.  This is a must watch and then follow it with this post and any other recent posts in Rob’s blog.
  • Jossef Goldberg has a great post on client profile in .NET4.  We recorded a video, to be posted in the next few days; look for it here via update to this post, or in the continuum show.
  • Tomorrow we are shooting the Touch video;  ironically they reached feature complete in beta2 today, maybe we can get a peek; video should be posted early next week. 
    [If you want to know why I am posting today instead of next week, we are doing LOB Tour in NY this weekend, so I am out on the road again. I hope you understand, post will be updated as we go]
  • WindowsClient.net now has a new section for the Cider designer. Karl Shifflett and the Cider crew will be putting videos there as they go. For starters, Mark Wilson-Thomas has a good “Lap Around Cider in beta1 .  


On the way to .NET 4.
Here is my view into the new features I am tracking and current (best guess) estimate on timelines. The list is not all inclusive, so let me know if I missed one you cared about.  note that this list focuses on new stuff;  I did not include all the bug fixes and minor improvements to existing stuff.

Huge WARNING!!  None of the below features are guaranteed.  Nothing is official until we RTM. 
Please do not make assumptions or plans based on this list.

Category

Feature

In beta 1

Expected by  beta 2

Windows 7 light-up

     
Multi-Touch Basic manipulation and inertia.
Raw touch events are not in.
Yes.  Beta1 + Raw touch.  A few tiny breaking changes.
  Taskbar integration Not in beta 1 Yes
  Vista + Win7 Native Dialogs Yes Same as beta1
  Ribbon (though it is not win7 specific at all). Not in beta 1 Ribbon will be shipping out of band still.  Next preview ships after beta2. It will RTM by .NET 4 RTM or earlier.
    Graphics& Text      
  Text enhancements Not in beta 1 Yes
  Cached Composition Not in beta1 Yes
  Support for Pixel Shaders written w/ HLSL 3.0 Not in beta 1 Yes
  Caret customization Not in beta 1 Yes
  ClearTypeHint Yes Same as beta1
Legacy effects get cut Yes. Old legacy Bitmapeffects are a no-op, unless it is one of the effects that are hardware accelerated. Same as beta1
Fundamentals & AppModel      
  XAML 2009 Beta1 Yes, minor changes.
  LayoutRounding Not in beta1 Yes
  Bindable Run Not in beta1 Yes
  Visual State Manager Not in beta1. In by beta2, now shipping in the framework.
  Animation Easing functions Yes Same as beta 1
  Datagrid Yes. Moved from toolkit to framework.  Minor bug fixes. Same as beta 1.
DatePicker Move from toolkit to framework. Minor fixes. Same as beta1.
  Full Trust XBAP Not in beta1 Yes
  Databinding improvements Not in beta1. Yes
     Deployment
Client Profile New client profile is in, but no web bootstrapper. Still needs to be compressed (for size). Yes, full functionality.
  Client Profile Configurator No. Will ship out of band. No. Will ship out of band.
          Tools      
  VS2010  Cider Cider has a lot of improvements.
Perf work is not done.
Yes.
VS2010 new Editor Since the text enhancements are not in the run-time, the editor does not get them. Yes.
       


Note: At PDC, we said that DeepZoom would be in WPF4. Unfortunately that feature has been cut. We just could not squeeze it into the schedule.  There are workarounds to it: you can host Silverlight inWPF using web browser control or using the Silverlight hosting APIs.
 

Details on  the features:
Below are high level descriptions around the features listed above. Must share that Ted Hu created the descriptions for a different document and I am shamelessly plagiarizing it. Thanks Ted.

Multi-touch
Windows 7 is introducing multi-touch input and manipulation processing, which Windows Presentation Foundation exposes. Multiple finger input will be exposed through existing and new input events, while new manipulation and inertia events will be exposed for developers to consume.

  • Multi-touch Manipulation and Inertia (Pan, Zoom, Rotate) events on UIElement
  • Raw Multi-touch events (Up, Move, Down) on UIElement, UIElement3D and ContentElement
  • Multiple capture supporting multiple active controls
  • ScrollViewer enhancement to support multi-touch pannning
  • Touch device extensibility
  • Future Surface SDK compatibility

Windows 7 Shell Integration
WPF 4 exposes several new Windows 7 Shell features to WPF developers These Shell features empower application authors to provide a richer, integrated user experience. The new taskbar is less cluttered and can convey more information at a glance. The Aero thumbnails support user commands. Jump lists provide access to contextual startup tasks and files available to the application.
WPF 4 will integrate Windows 7 JumpList functionality, including:

  • Tasks
  • Items
  • Recent and Frequent Lists integration
  • Custom Categories

Taskbar integration including:

  • Progress bar
  • Overlay Icon
  • Thumbnail buttons with commanding support
  • Description Text
  • DWM Thumbnail clipping

Text enhancements
WPF 4.0 Beta 2 introduces a new text rendering stack which allows for much clearer text rendering.  This change adds the necessary knobs to allow WPF text to look virtually indistinguishable from Windows’ traditional GDI-rendered text.  The clarity improvements also dramatically improve readability for many East Asian languages.

 

 


ClearType hint
ClearTypeHint allows app authors to enable cleartype when rendering text to IntermediateRenderTargets, where it would normally be disabled by the system.  The system normally disables cleartype on IRTs because Cleartype only works properly when it’s rendered to an opaque surface, and it’s extremely difficult for the system to determine if an IRT will be rendered with transparency.  By Setting this to true, you’re basically letting the system know that the IRT is transparent.  This means you can now enable cleartype with layered windows, in Visual/Drawing brushes, in Effects, and in 3D if you so desired it. 

Full-Trust XBAP
Starting in WPF 4.0, the ClickOnce elevation prompt is enabled for XAML Browser Applications (XBAPs) in Intranet and Trusted Zones, making it easier to deploy full-trust XBAPs. For XBAPs that require security permissions greater than the minimum code access security (CAS) permission grantset of the Intranet and Trusted Zones, the user will be able to click 'Run' on the ClickOnce elevation prompt when they navigate to the XBAP to allow the XBAP to run with the requested permissions.

LayoutRounding
WPF 4.0 will adopt the LayoutRounding property, originally introduced in Silverlight2. WPF’s layout engine frequently calculates sub-pixel positioning coordinates. This can lead to rendering artifacts as elements positioned on sub-pixel boundaries are antialiased over multiple physical pixels. LayoutRounding will force the layout engine to place elements on whole pixel boundaries, thus removing most of the rendering artifacts caused by this problem.

Bindable Run
The Run class has had a simple CLR property Text since the first release of the framework. In WPF 4.0 we have backed Run.Text with a dependency property. Among the many benefits of being a DP, Run.Text now supports data binding. One-way binding (from data source to Run.Text) is fully supported, and two-way binding is supported as long as the Run is not modified via the Text OM or from a RichTextBox.

Selection and caret customization
Simple app customization is a great WPF strength. In the past, the selection color and caret color for text input and reading controls (TextBox, RichTextBox, FlowDocumentReader, etc...) has been hard coded. WPF 4.0 will introduce the SelectionBrush and CaretBrush properties. These properties will allow developers to control the brush used to draw both selection and carets in many WPF controls.

Animation Easing functions
Is the exact same functions we announced in Silverlight 3;  I can not tell you who created them first; funny how schedules work; but really nice to have compatibility.

BindingExpressionBase.ValidateWithoutUpdate does for a single binding expression what BindingGroup.ValidateWithoutUpdate does for a binding group – namely it starts the validate/update process but stops just before writing a value back to the source item

When BindingGroup.SharesProposedValues is true, the binding group will keep track of proposed values even when the UI elements that hold them are replaced.  This supports a UI design pattern used by DataGrid (for example), where only one source property is presented with an “editing template” (containing editable controls – TextBox) while the other properties are presented with “display templates” (containing non-editable controls – TextBlock).   As the user focuses a new property, its display template is replaced by an editing template, while the previously focused property’s editing template is replaced by a display template.  The BindingGroup now manages the proposed value (if any) held by the old editing template, so that it can be displayed (if possible) in the display template and written back to the source when the user commits the binding group

LayoutRounding
Speaks for the feature already in Silverlight, where the layout system rounds any non-integral values at the time of a layout pass. This helps prevent the sub-pixel anti-aliasing effects that people describe as "blurriness"

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.

http://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
http://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 ).
http://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:
http://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.

Our second stop in the “WPF for Line Of Business Tour”  was London, last week.  londonxamlized

We had a full-house with people from Germany, Italy, France,  Poland, Switzerland, Spain, United Kingdom, and probably other countries. 

The content evolved (a small %) from the LA training:
Updated decks;  Updated demos
 
London attendees, THANKS for joining us!!  It was a pleasure!
New York,  Chicago, & Phoenix get ready!  

PS.- While in London, we also got to xamlize with WPF disciples Marlon Grech and Sacha Barber.  I had not met them in person before, but I can now confirm: their passion and knowledge on WPF and .NET is as good as you read on their blogs.  Cheers!

You know the drill. Raw/unedited conversations from our internal discussions. 



Subject: Datagrid SelectedIndex = -1 not working

I am using the toolkit Datagrid. When i delete a row from the datagrid, i dont want anything to be selected. Hence i am setting it's SelectedIndex to -1. But it is not working. The first row gets selected everytime a row is deleted.

Answer:
SelectedIndex = -1 works only when DataGrid.SelectionUnit is FullRow. The following code should work…

if(MyDataGrid.SelectionUnit == DataGridSelectionUnit.FullRow) {

                MyDataGrid.UnSelectAll();

}

else {

                MyDataGrid.UnSelectAllCells();

}


Subject: Can I set WPF title bar color programatically?

In Vista with Windows Vista theme, I can change the title bar color by changing the window color in “Control Panel -> Appearance and Personalization -> Window Color and Appearance”. I wonder if I can change the title bar color in my code instead of changing the window color?

Answer:
There are no wpf specific api's to set the Windows Theme settings; Wpf will pick up the setting and respect them but not the other way around.  Using   uxtheme.dll and some pinvokes it might should be possible to change the look of the title bar for your application or the computer. Try:
http://pinvoke.net/default.aspx/uxtheme.SetSystemVisualStyle and http://www.codeguru.com/vb/gen/vb_misc/gamesandfun/print.php/c14319__6/


Subject: Clipping a Bitmap in memory

Is there a way to clip an image only “in memory”? I’m looking for a technique similar to the code-only approach used with TransformedBitmap?

Answer:
Try CroppedBitmap


Subject: Default Style

I have a custom control based on an Expander that has an additional boolean property.  Is there a way to write a style for my controls such that when my property is false I return whatever the default style for the Expander is and if it is true I return my own variation?

Answer:
We have a protected DefaultStyleKey property that is used to query the Default Style for a control. Since you are subclassing the Expander control, you could listen for changes to your new custom Boolean property and change the DefaultStyleKey property in accordance. i.e when your property is false the DefaultStyleKey should be typeof(Expander) and when it is true it should probably be typeof(MyCustomExpander). This will cause your control to automatically pick up the right DefaultStyle in these two cases.


Subject: finding relative positions

I am having an issue finding relative positions of elements inside of their containers. If an element is automatically aligned (or placed without specific positions) there doesn’t seem to be a way to find its relative position to its parent, which I think should be something that is be available on all elements and am curious as to why this is not accessible.

Answer:
Try Visual.TransformToAncestor(Visual ancestor), passing in the parent as “ancestor”?


Subject: Coercion on inherited context
Thread is too long, sharing the conclusion though.

Answer:
Coercion on inherited context is broken; there is a bug for this


Subject: Full screen window.

This works:   <Window Topmost="True" WindowState="Maximized" WindowStyle="None" … >  but this does not : this.WindowState = WindowState.Maximized;  this.WindowStyle = WindowStyle.None;   this.Topmost = true;
why??

Answer:
Order matters. must style first ..

this.WindowStyle = WindowStyle.None;
this.WindowState = WindowState.Maximized;
this.Topmost = true;


Subject: Guidance redistributing Microsoft.Expression.Interactivity.dll?

Answer:
Because there is no Go-Live license associated with Blend 3, please do not redistribute these components publically outside of sample code. When Blend 3 RTMs, we will be releasing an SDK that includes, among other things, the Behaviors runtimes. Do note that you will be responsible for servicing your application with any updates we provide to the behaviors, etc.

----------

Subject: hittest and ishittestvisible.

I’m setting a user control as IsHitTestVisible=false; but the VisualTreeHelper.HitTest still be able to hit itself or its children.
Is there a hittest function that I can call to not to hit the user control and its children when such flag is set?

Answer:
You should be able to use UIElement.InputHitTest to work-around this behavior.
Note that even then, it will be hit testable, it’ll just be considered  part of the parent in terms of where the event is raised, etc.  That is, this doesn’t make an element “transparent” to hit test.


Subject: How to add attribute to App.Main when it is in generated code (App.g.cs)?

I would like to add the LoaderOptimization attribute to my WPF Application’s Main function but that is being generated automatically in App.g.cs by the App.xaml compilation

Answer:
The easiest way:
1. Open the generated App.g.cs, take the Main() method, copy it to your code, and customize as you need.
2. Change the Build Action of your App.xaml from ApplicationDefinition to Page. (It’s not a “page” in the common sense of the word, but this is the generic XAML compilation task, which enables having code-behind.)


Subject: HwndHost loses track of focus when keyboard used

I have a customer who has a WPF application hosting native windows via HwndHost.
They expect that if the focus is on a control in their native window, they switch to another application, and then switch back then the focus will remain on their native control.  This is the behavior they get if the focus is on a WPF TextBox when the foreground application changes, and this is the behavior they get if the focus is set onto their native control with the mouse and there is no keyboard input; however, if there is any keyboard input then the focus ends up on the parent WPF window rather than on their native control.

The problem appears to be that the focus should be reset when HwndKeyboardInputProvider.FilterMessage handles the WM_SETFOCUS sent to the top-level WPF window; however, the _active flag gets out of sync if there is keyboard input.  If it is true the HwndKeyboardInputProvider thinks the window was already active and so doesn't forward the focus to the child window.  In both cases, _active is set to false when FilterMessage handles WM_KILLFOCUS as the focus moves to the native child.   If there is any keyboard input, HwndKeyboardInputProvider.ProcessKeyAction calls ReportInput which sets _active to true.

It looks like there are several known issues around this area, but I'm not sure if they cover this or not.  Does anybody know if this is already known (and if so, which bug number?)

We can work around the problem by subclassing the top level window and tracking the activation and focus ourselves, but there already appear to be several subclass methods poking their fingers into this area and I'm concerned they might conflict.  Am I just being paranoid?  Is there a better way around this?

Answer:
We know how the logic in HwndKeyboardInputProvider is broken. Opened a bug for it.
There’s probably no great workaround in general, but for a specific application this may work: Preview input from our ComponentDispatcher (assuming WPF is running the message loop) and if the currently focused window is a child one, dispatch keyboard input messages straight to it. The snippet below does this. The most major side effect is that you lose access to accelerators in the main window. But if that’s an issue for the particular application, it’s probably resolvable: Get the HwndSource of the containing window and call IKeboardInputSink.OnMnemonic() on it.

     public partial class Window1 : System.Windows.Window

     {

           public Window1()

           {

                InitializeComponent();

            ComponentDispatcher.ThreadPreprocessMessage += new ThreadMessageEventHandler(OnComponentDispatcherPreprocessMessage);

           }

        void OnComponentDispatcherPreprocessMessage(ref MSG msg, ref bool handled)

        {

            if (msg.message >= Win32.WM_KEYFIRST && msg.message <= Win32.WM_KEYLAST)

            {

                IKeyboardInputSink sink = _hwndHost1;

                if (sink.HasFocusWithin())

                {

                    Win32.TranslateMessage(ref msg);

                    Win32.DispatchMessage(ref msg);

                    handled = true;

                }

            }

        }

     };

    static class Win32

    {

        [DllImport("user32.dll", ExactSpelling=true)]

        public static extern bool TranslateMessage([In, Out] ref MSG msg);

        [DllImport("user32.dll")]

        public static extern IntPtr DispatchMessage([In] ref MSG msg);

        public const int

            WM_KEYFIRST = 0x0100,

            WM_KEYDOWN = 0x0100,

            WM_KEYUP = 0x0101,

            WM_CHAR = 0x0102,

            WM_SYSKEYDOWN = 0x0104,

            WM_SYSKEYUP = 0x0105,

            WM_KEYLAST = 0x0108;

    };

--------------

Subject: Managing Z-Order of Topmost windows in WPF

I have an application where I have several popup windows that I use to display information to the user. My problem is that I want to be able to programmatically control the z order of these windows so that they overlap in a way I can control.

Answer:
Try Window.Owner.  http://msdn.microsoft.com/en-us/library/system.windows.window.owner.aspx
Setting
an owner window can help you predefine the Z order. If you need finer control, you can call the native SetWindowPos() function. Typical flags to pass for this purpose are SWP_NOSIZE| SWP_NOMOVE, possibly also SWP_NOACTIVATE.


Subject: Memory leak in SplashScreen

Answer:
There isn’t really a good work around for 3.5 SP1 other than implementing your own splash screen instead of using the built in one.  We’ve published a blog entry with sample code here that you can use: http://blogs.msdn.com/jgoldb/archive/2007/12/10/splash-screen-to-improve-wpf-application-perceived-cold-startup-performance.aspx.


Subject: TextBox selection color

It seems from searching the web that there is no way to customize the color of selected text in a WPF TextBox control. Is this true, and is there any workaround?

Answer:
This will be fixed in WPF4.  No easy workaround interim.  If you want to know the details:


Subject: Loading a resource for an app and for a referenced assembly

We have an API in our app that loads a resource.  We use this URI pack://application:,,,/Resources/icon_back_arrow.png and everything works just fine when using the application directly.

Now we’ve written some tests for this API which load our app as a referenced assembly.  The resource is not being found and I’m pretty sure it’s because of the pack URI.

I’ve found I can fix the problem if I use this URI pack://application:,,,/seahorse;component/Resources/icon_back_arrow.png  but it seems weird to me that to use resources programmatically I need to encode the name of the assembly into URIs for resources.

Is there a way of loading resources in code that will work both in the application and referenced assembly case?

Answer:
Set Application.ResourceAssembly


Subject: Is there any way to let a child class automatically pick up its base class's style

I have a Control class ChildFoo defined as a subclass of control class Foo. And I defined a style with TargetType=”{x:Type Foo}”;The problem here is: I wish the ChildFoo control can automatically pick up the style defined for Foo.

Answer:
http://social.msdn.microsoft.com/forums/en-US/wpf/thread/28b4357a-1d9d-4af3-8fe5-87f1b01fe150/ 


Subject: Unni is blogging again. Nice posts of Blend extensibility.

Answer:
http://blogs.msdn.com/unnir/archive/2009/03/27/a-sample-that-shows-the-new-blend-design-surface-extensibility.aspx
http://blogs.msdn.com/unnir/archive/2009/03/22/writing-a-design-time-experience-for-a-silverlight-control.aspx


Subject: Updating all bindings for an object
How can I update all bindings for an object?  With out firing propertyChanged for each property?

Answer:
Raise  PropertyChanged with “”  as the propertyname (e.g. PropertyChanged (this, new PropertyChangedEventArgs(“”))  ;


Last week we had our first stop in the WPF for LOB tour: Los Angeles.    hOLLYWOODxamlIZEDThe training went very well!  Attendees were very engaged and they kept up with a lot of content in a short time-span; from what I heard, they learned quite a bit.

Karl and I learned a bit too! We are already refining our content for the next stop:
London (on 5/15 and 5/16) at the
              Radisson Edwardian Heathrow Hotel
              140 Bath Road
              Hayes Middlesex , London

Thanks LA! The content for the training is here: decks (30 mb), demos (15mb) 


If you have not signed up for your training ( in London,  NY, Chicago, or Phoenix), I recommend you get to it soon; London and NY are already full, but we are adding names to the waiting list.   Chicago and Phoenix are getting there!.   Huge thanks to all those helping us spread the word!

London residents, see you soon!    LA attendees, thanks again!! It was a lot of fun!!

More Posts Next page »
 
Page view tracker