Jaime Rodriguez
On Windows Store apps, Windows Phone, HTML and XAML

  • Jaime Rodriguez

    List of features to track in WPF4 and the details on beta1

    • 15 Comments

    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"

  • Jaime Rodriguez

    WPF Discussion, 090522

    • 1 Comments

    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.

  • Jaime Rodriguez

    Thank you London. here is the content

    • 4 Comments

    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!

  • Jaime Rodriguez

    WPF discussion, 090501

    • 2 Comments

    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(“”))  ;


  • Jaime Rodriguez

    Thank You LA!! Here is the content

    • 7 Comments

    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!!

  • Jaime Rodriguez

    Announcing WPF TestAPI 0.2 release

    • 1 Comments

    Last week, the WPF test team released a new version of their Test API: 0.2.  You can download the new release from their codeplex site.

    The Test API is a library with utilities for testing WPF and Windows Forms applications. 

    In their 0.2 release, the library includes APIs to simulate input and do visual verification; it also includes handy utilities that can be used for tasks beyond testing, like a command line parsing ,  and APIs to drive the WPF dispatcher.
    The library is not VSTS specific; in their 0.2 releases they added nUnit and xUnit samples.

    The best way to learn about the lib this is to download it, play with it and read their docs;  that said, if you want to learn more before you download, Ivo the WPF test manager has some good blog posts on their 0.1 release. 

    For feedback,  you can go to the codeplex forums.  They need help prioritizing the features in the next version. Among the most interesting ones, I see controls verification, state management APIs, property comparisons, performance, and leak detection.  I am voting for the last two!!  How bout u?

  • Jaime Rodriguez

    Robby Ingebretsen’s design for developers MIX09 workshop now online..

    • 4 Comments

    The MIX09 team just posted Robby Ingebretsen’s:   “Design for developers workshop.


    Robby knocked it out of the ball park with his workshop.   
    This is a must watch (multiple times) for most developers wanting to understand design.
    I hope you enjoy it as much as every attendee did.  Click on the image on the right to go to MIX site and watch.

    We posted three videos as an asx. If you want to download, here are direct links:
        Part One: Process
        Part Two: Composition
        Part Three:  Visuals

    Enjoy!!


     

     


     

    A few comments or disclaimers around workshops:
    The workshops and pre-cons are not posted online because they cost extra. So for other conferences, please do not expect this.
    In this case, workshops were recorded to test the cameras and accidentally posted on-line earlier, but encoding was not good; we heard from lots of people that they wanted to watch it,  including people who had paid to attend; when we asked those that paid if it was OK to post for everyone they agreed, so thank them for it, but again, don’t assume this will repeat again (it is not up-to-me).

    What about the other workshops?
    Hiking Mt. Avalon (my workshop) should be posted next. The Mix online guys are doing this one at a time so they can say I owe them four favors instead of one; either that or it takes a day to encode and they are working on it.
    We are looking at the other workshops to see if the quality is good enough.  I can’t promise any other workshops yet; I do know that Molly’s workshop was not recorded.

  • Jaime Rodriguez

    wpf discussions.. 090403

    • 1 Comments

    You know the drill.. raw, unedited, yet deep and useful WPF conversations !!


    Subject: Changing Resources from Triggers

    I have a complex ControlTemplate that I want to change colors when the mouse is over it.  The colors are used at various places deep within the template, and some are even in nested templates …. …

    Answer:
    To change Resources on a Trigger is to change a non-DP property on a Trigger. WPF does not currently support this. As a workaround could you try the following pattern?

    <ControlTemplate>
      <SomeElement1 x:Name="element1">
        <SomeElement1.Style>
          <Style>
            <Style.Resources>
              <SomeResource1 x:Key="blah" />
            </Style.Resources>
          </Style>
        </SomeElement1.Style>
        <SomeElement1.Template>
          <ControlTemplate>
            <SomeElement1_1 SomeProperty="{DynamicResource blah}" />
          </ControlTemplate>
        </SomeElement1.Template>
      </SomeElement1>
      <ControlTemplate.Triggers>
        <Trigger Property="AnotherProperty" Value="anotherValue">
          <Setter Property="Style" TargetName="element1">
            <Setter.Value>
              <Style>
                <Style.Resources>
                  <SomeResource2 x:Key="blah" />
                </Style.Resources>
              </Style>
            </Setter.Value>
          </Setter>
        </Trigger>
      </ControlTemplate.Triggers>
    </ControlTemplate>

    Subject: Creating WPF window prevents application from closing
    Window window = new Window();
    Putting this line anywhere in my WPF application without actually using this window variable prevents my application from closing when I hit the main window close button. Why would creating an instance of Window have this effect? Only if I add a subsequent window.Close() call does my application shut down correctly.

    Window window = new Window();
    window.Close();

    Answer:
    If you do Application.Current.Shutdown() your app should close.
    I assume you’re doing Application.Current.MainWindow.Close().  There’s a property on Application called ShutdownMode.  The default is OnLastWindowClose.  Since you’ve created a window and not closed it, your app will never shut down.  You can change Application.ShutdownMode to OnMainWindowClose, and you should be fine.


    Subject: Coerced value not reflected in control or others bound to it as sources

    I have the following xaml. The CustomTextBox overrides metadata for the Text Dependency Property, which calls a coerce method, which upshifts whatever the user enters. However, the upshifted value does not show up in either TextBox. If I move the binding to the 2nd text box, so it binds to the first, it will display the upshifted text correctly. Why is the upshifted string not showing up in the original case (i.e. as below)?

    <StackPanel Margin="20" VerticalAlignment="Center">

    <Label Content="Target TextBox (with coercion to uppercase)"/>

    <src:CustomTextBox x:Name="TargetTextBox"

    Text="{Binding ElementName=SourceTextBox,

           Path=Text, Mode=TwoWay,

           UpdateSourceTrigger=PropertyChanged}"

    Margin="0,0,0,20"/>

    <Label Content="Source TextBox"/>

    <TextBox x:Name="SourceTextBox" IsReadOnly="True" Background="LightGray"

    Margin="0,0,0,20"/>

    </StackPanel>

    Answer:
    Here’s a bit of background on coercion. The classic case of coercion is the Slider control where the Value property’s value needs to always lie between the MaxValue and the MinValue. So in this regard we envisioned Coersion to be a view concept. Hence we made a design decision not to propagate coerced values through data Binding. Thus the fact that you don’t see a coerced value on CustomTextBox.Text propagate through the Binding back to the source is ‘By Design’. Yes it can be argued that when Binding is used in the way you’ve shown below to bind two UI pieces then one would want to propagate the coerced value through the Binding. Sam Bent (our Data Services guru), has some thoughts on building some configuration parameters on Binding to allow this. However none of that exists in the platform as of today. As for a Binding on a regular TextBox.Text property displaying the upshifted Text, the reason is that the value at the source is transferred as is to the target of a Binding. The special rule about coercion only comes into play when the value at the target is being coerced. 


    Subject: Creating Bindings in a Data Template

    I’m trying to create a DataTemplate where some non-FE objects bind to the DataContext of the DataTemplate.  My XAML looks something like this?

    <DataTemplate DataType="{x:Type api:SeahorseItem}">
          <Button CommandParameter="{Binding RelativeSource={RelativeSource Self}}">
            <con:DoubleClickButton.Command>
              <con:MetaCommand CommandParameter="{Binding}">
                <con:MetaCommandEntry Command="FocusCommand" CommandParameter="{Binding }" />
                <con:MetaCommandEntry Command="OpenCommand" CommandParameter="{Binding }" />
                <con:MetaCommandEntry Command="OpenInBackgroundCommand" CommandParameter="{Binding }" />
              </con:MetaCommand>
            </con:DoubleClickButton.Command>
          </Button >
        </DataTemplate>

    When I run my application I get the following error message:

    System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:(no path); DataItem=null; target element is 'MetaCommandEntry' (HashCode=51095287); target property is 'CommandParameter' (type 'Object')

    When I actually debug this, the CommandParameters on my entries and the command itself are null.  I’ve done some digging, and it seems that my problem is that my objects are not FEs, and as a result not part of the inheritance tree.  I also saw a neat trick that allows me to make my objects a part of the inheritance tree by making them freezables.  This worked for the MetaCommand, allowing it’s binding to work. But the Entries still evaluate to null. 

    Answer:
    Could you make the collection property that holds on to the MetaCommandEntries be of type FreezableCollection<MetaCommandEntry> and MetaCommandEntry should also subclass Freezable. The reason for these changes is that InheritanceContext is internal to the framework and Freezable and FreezableCollection are the only two non-FE/FCE public classes that support it.


    Subject: DataGrid different template for new row problem.

    I’m trying to show a different template for the last row of my DataGrid to show not the default row template but show a line of text say “Click here to add new item”.

    I came across this blog http://blogs.msdn.com/vinsibal/archive/2008/11/05/wpf-datagrid-new-item-template-sample.aspx

    I improved it a little bit by listening to InitializingNewItem event and saved the Dispatcher trick. But I still need to listen to several event, use VisualTreeHelper to set the focus on the first cell of last row. I wonder if there is a easier way to do this in general. I believe this is a very common scenario.

    Answer:
    We hear you. We will look to make this scenario easier in a future release. But what you see in the blog is what we have today.


    Subject: Font change events?

    I need to detect when font setting for a specific element in my FlowDocument changes, either because it’s (local) font property or its container’s property (inheritable) changes. Is it possible? (I do not see an event that looks that way; I need to change some other properties because of the font change). Alternatively, is there any way for me to detect that the document is about to re-render and do these mods then?

    Answer:
    You could try DependecyPropertyDescriptor.AddValueChanged. The dependency property would be TextElement.FontSizeProperty


    Subject: How to display 1st underscore in Label ?

    I would like to display 1st underscore “_” in Label. I know 1st “_” means keyboard shortcut. But he don’t use shortcut but want to display it. How to escape make “_” shortcut ?

    Obvious Answer:
    Try double “_” as markup below.
    <Label Content="__Label"/>

    Follow-up:
    Yes, I did, but I have to add extra underscore to all underscore such as A__B__C__D instead of A__B_C_D.

    Next answer:

    The simplest solution would be to use TextBlock instead of Label. Otherwise, you could re-template Label to change RecognizesAccessKey to false :

        <ControlTemplate TargetType="{x:Type Label}">
          <Border ...>
            <ContentPresenter ... RecognizesAccessKey="False" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
          </Border>
          ..
        </ControlTemplate>
    

    Subject: Is there any easy way to get the size of a ImageSource

    I'm implementing a cache for ImageSource. I was looking the documentation but I could not find a easy way to get the Size (in bytes) of a ImageSource. Is there a easy way to do that?

    Answer:
    A size property doesn’t make sense for all implementers of ImageSource. The two platform ones (according to MSDN) are DrawingImage and BitmapSource. DrawingImage is specified in XAML, so its size would not be representative of a pixel width x height x depth measure in bytes.

    Take a look at the ImageSource documentation and inheritance tree:

    http://msdn.microsoft.com/en-us/library/system.windows.media.imagesource.aspx

    You can get a size for the pixels of a BitmapSource using PixelWidth, PixelHeight, and Format.BitsPerPixel. Obviously the object itself can store some more information depending on the implementation. So I think you might want to implement a cache for the BitmapSource class rather than ImageSource


    Subject: Closest to immediate-mode rendering in WPF

    What is the closest I can get to immediate-mode rendering in WPF? Right now I’m overriding OnRender and basically re-populating the DrawingContext on every frame (since a physics engine is involved, everything moves). Is that the best way?

    Also, I noticed that there is no way to apply pixel shaders in the DrawingContext like we can do in XNA. Is there any (potentially hacky) way to push a pixel shader into DrawingContext? Seems odd that we can push bitmap effects but not hardware accelerated effects.

    Answer:
    That’s as close as it gets. Not sure if it matters to you, since you’re changing everything every frame, but it’s probably worth noting that the dirty region logic operates at the Visual level. Which is to say if you draw everything in 1 DrawingContext, you get no dirty subregion support for all that content.

    Having said that, what exactly is changing in your scene? If things are moving/rotating while maintaining a rigid shape, it might make more sense to draw everything once, then simply update the transforms every frame with the physics engine inputs. This is much more “WPFy”, and if it fits within the constraints of your system, it should also be more efficient than changing the DC content every frame.

    No way to push an effect in a DC. The method of drawing you’re using is not really the one for which WPF is optimized.

    Bitmap effects are going away. If you pick up a 4.0 beta build, they’re already gone.


    Subject: Making one color in a bitmap transparent

    I’m fairly new at WPF, so if there is an obvious answer to this question, it’s likely the right one.

    I’m trying to convert some old WinForms code to WPF and I’m running into a snag displaying Bitmap images.  All of the bitmaps in my application have the same background color which is intended to be displayed as transparent.  In WinForms I could achieve this effect by creating an ImageList and setting the TransparentColor property to be this particular color. 

    How can I achieve the same effect with WPF?

    Answers:

    There's no default support in wpf to do this.  However Dwayne has blogged about how to do this.http://blogs.msdn.com/dwayneneed/archive/2008/06/20/implementing-a-custom-bitmapsource.aspx
    If you have a small number of bitmaps, it’s probably easier to make them transparent yourself in a photo editing app and save as PNG.

  • Jaime Rodriguez

    Announcing the "WPF for LOB" Training Tour..

    • 33 Comments

    After our m-v-vm training sold out, and most of the march trainings were filled within days, I am delighted to announce our new series of WPF trainings for April/May/June.   

    Karl Shifflett and I created our best offering to-date: two days packed with WPF, optimized for building business applications, and in your neighborhood. We are hitting five different cities this time!!

    Please join us, and please help us spread the word about the training!!

    Update on 4/2  -- Added registration tips; a lot of people were wondering about partner requirements; there are none. This training is open to every one. Sorry for asking those questions, we are tagging on existing infrastructure for registration.

    Update on 4/8Dates are now final and the good news is the events were moved up. The NY and PHX dates changed, but registration opened with right dates so any one who registered saw the right ones!

    Here is the full-invite:


    Overview
    This two day training is designed to teach developers how to create Line of Business (LOB) applications using Windows Presentation Foundation (WPF).  

    • Day One is an introduction to the WPF graphics subsystem, the tools used to build WPF applications, and the core UI services: styling, data binding, templating, layout and input-
    • The second day begins with interop (Windows Forms and Win32)  and then quickly dives into LOB topics, including building applications using the Model-View-ViewModel pattern, creating unit testable applications,  implementing data validation, and error handling.  

    After completion, attendees will have a solid understanding of WPF, its advantages over other Microsoft UI platforms, and how to use the M-V-VM pattern to create great WPF LOB applications.

    Date, Location, and Logistics

    Location

    Dates

    Click here to register (see tips below)

    Los Angeles, CA

    4/24 -4/25

    www.msregistration.com/wpflobLA

    London, UK

    5/15 -5/16

    www.msregistration.com/wpflobUK

    New York, NY

    5/29-5/30

    www.msregistration.com/wpflobNY

    Chicago, IL

    6/12-6/13

    www.msregistration.com/wpflobIL

    Phoenix, AZ

    6/5-6/6

    www.msregistration.com/wpflobAZ

    Registration tips:
    If you are not a partner or don't know if you are:
          When asked "are you registered" select No.  Select "Visiting partner" under Partner Level.
          Get creative on the Partner Type;  if in doubt, we are all "System builders"
     

    Format:
    Instructor-led training from 9 AM to 5:30 PM.   15 minute breaks every couple hours. 45 minutes lunch around mid-day.
    Food:
    Breakfast, lunch and afternoon snacks are provided.

    Cost
    The training is FREE. You do need to register prior to the event, but there is no cost.  You can register for one or two days. Registration is first-come-first serve, sign-up as early as possible to reserve your spot!


    Detailed Agenda

    • Day One:
      • Lap Around WPF
      • WPF Tools ( Blend, Visual Studio 2008)
      • Graphics Subsystem
      • Layout
      • WPF Fundamentals and new concepts
        • Application Model
        • Dependency Properties
        • Trees (logical & visual)
        • Events
        • Threading
        • Resources
      • Controls
      • Styling
      • Templating
      • Q&A with instructors at end of day
    • Day Two:
      • WPF integration with Win32 and Windows Forms
      • Data binding
      • Introduction to Model-View-ViewModel
      • Commanding in M-V-VM
      • Views, Navigation and Transitions
      • Data Validation
      • Error handling, Model dialogs, Logging
      • Unit Testing
      • MVVM & LOB tips and tricks
      • Q&A with the instructors

     

    About the instructors
    Karl Shifflett is a software architect, former Microsoft MVP, current Code Project MVP and MCAD from Bellevue, Washington. He is currently working for Microsoft on the Cider Team as a Program Manager II. He has been designing & developing business applications since 1989 and transitioned to .NET in March of 2003. In April of 2007 he joined the list of WPF and Microsoft Expression fanatics & evangelists. He is a member of Team Mole that delivered Mole Visualizer For Visual Studio to the world. He is the author to XAML Power Toys and loves WPF LOB.  Karl’s Blog: http://karlshifflett.wordpress.com/

    Jaime Rodriguez is a Senior Technical Evangelist at Microsoft. He focuses on WPF and Silverlight.   For the last four years, he has helped a lot of enterprises and ISVs adopt WPF in large scale, mission critical, projects. 
    Jaime has been doing software development for fifteen years. Prior to Microsoft, he worked at Xerox, HP, Cerner and GeoAccess.   He joined Microsoft 9 years ago, he spent the first four years as an Enterprise Architect Consultant in Microsoft Services, and the last five he has been a client evangelist covering Windows Forms, WPF and Silverlight.  Jaime’s blog is at http://blogs.msdn.com/jaimer


  • Jaime Rodriguez

    MIX09 recap series part3, The Microsoft Client Continuum

    • 1 Comments

    In  part 2 of the series, I explained the different target scenarios for Silverlight and Windows Presentation Foundation (WPF). 

    I think at MIX09, we could have emphasized a bit more strongly our Microsoft Client Continuum. We demonstrated it a lot, but maybe did not take time to explain it, or explicitly call it,  so I wonder if every one knows about it externally?

    The “Microsoft Client Continuum” is our mission to empower you to create the Best User Experiences across all your customer’s touch points.

    Today, you can reach customers on a web application (RIA), on Windows, on Surface, on Mobile devices, etc. 
    On part 2 of this series, I explained that one single run-time is likely not flexible enough to address the conflicting requirements (size vs. features, or full-trust vs. sandboxed) from all scenarios; if you want to provide the absolutely best experience across multiple touch points, you will likely end up at least compiling the application twice or having small optimizations for each touch point; this is where the Microsoft Client Continuum offers some significant advantages over other solutions. 


    The client continuum uses .NET as the single skill, single toolset needed to create immersive client applications.

    The continuum facilitates great User Experiences with tools that empower both designers and developers; these tools share a common declarative languages to represent UI and interactions.

    The continuum thrives on reuse: skills reuse, tools reuse, and code reuse.

     

    At MIX09, on the Silverlight and WPF front, we demonstrated the continuum a lot:

    There were plenty other demonstrations of the continuum in action, and there are plenty more to come.  One part that I really enjoyed at MIX was talking to a lot of customers, and partners, who are writing apps that span across the continuum.

    For those wondering about the choice between WPF and Silverlight, keep the continuum in mind and rest assured you are not making the wrong decision with either technology.

    • For developers and designers, learning our continuum technologies is a great investment; you learn XAML and the tools once and you can reuse it across mobile, desktop, RIA, and Surface applications.
    • For businesses, you can prioritize for what you need today (desktop or RIA) and later on create the appropriate companion.  Your skills, tools and code investments are preserved. 

    A few disclaimers on status today and future for the Continuum:

    • We are not done with the Continuum. If you want to share code, do plan ahead; be aware of the current platform differences, expect those to decrease quickly but don’t expect them to go away 100%, Silverlight will likely stay a subset of WPF (to keep it small and RIA optimized).  MIX09 was a great step in the right direction, there are plenty of new features in SL3 that make the compatibility with WPF higher.
    • There will be more convergence on both sides. Both WPF and Silverlight will continue to grow and innovate on their scenarios, but on each release, each run-time should also pickup features that the other run-time added.  WPF will pick up Silverlight features (like VSM or controls) and Silverlight will continue to add features from WPF.  

    Closing the series:  
    I think MIX09 was a great conference!  The features and products announced are very exciting.  Microsoft demonstrated strong innovation and adoption on the RIA space,  and a strong commitment to User Experience and designer tools.  Because MIX09 is a web conference, we shared our web message and this likely confused attendees on our commitment for WPF; the reality is that we are equally committed to WPF and Silverlight, because we need both technologies to deliver on our Client Continuum. 

  • Jaime Rodriguez

    MIX09 Recap series part2 , what about WPF

    • 3 Comments

    In between all the positive feedback at MIX, there was a lingering question that I read a lot on twits, blog posts, and heard at the Q&A from some sessions and I think we missed it during our planning; I felt it is one of those “we can not see the forest cause the trees are on the way” mistakes.   Do you know what the question is??  

    Yes, it is “With Silverlight out of the browser, is WPF dead?” ..

    Here is my personal take as a person who spends a lot of time with both of these teams and with customers using the technologies ( very often at the same time):

    WPF and Silverlight address different scenarios and though they look alike, it is unlikely that in the short-term, one replaces the other.

    The long answer is that the scenarios each technology addresses are different enough that they have conflictive requirements.  
    I see the choice between these two platforms as a trade-off between:

    Size vs. Features
    Full-trust (with native interop) vs. Secured or Sandboxed

    Expanding even further:

    Silverlight addresses our RIA needs. A good Rich Internet Application (RIA)run-time needs to be:

    • Cross-platform.  This likely means the frameworks can’t become too exploitive of OS specific features and can’t integrate that well with the host OS. It is a lot of work to create a comprehensive application  framework (like .NET) for cross-platform.
    • Easy to deploy and small in size.  Web technology needs to install quickly, and with no risk of disrupting the desktop.  When it comes to RIA frameworks, the trade-off between features and size is very tough. Compromises must be made when necessary (backing up my point that the framework is unlikely a full-desktop application replacement due to the size constraint).  
    • Secured (or better yet, sandboxed).   Internet software can’t be easily trusted because today there is no easy way to assign different trust levels across the internet.  It is better to run sand-boxed so users are safe, than to put desktop at risk, so most RIA software is therefore sandboxed. This is critical to the success of RIAs! 
      You can ignore it and get lucky (for a little while) but I think it will eventually bite those that do ignore it.  Microsoft has learned that lesson before, and we are not looking to compromise that again (ever?).  
    • Faster and richer than any thing standards and web-based software (else why use it?).

    WPF addresses our Windows (desktop) application needs.  A good desktop application needs to be:

    • Exploitive.  If it runs on a single OS, it better take advantage of it. Features like desktop and shell integration, drag & drop, hardware acceleration, etc.   If the software runs on a platform that supports extended features like touch (in Windows7 or Surface), the app should embrace and support the features.
    • Comprehensive and Powerful. If the run-time is installed once,  there is no reason for it not to be a full framework ( full 3D, media, documents, accessibility, storage and databases, a complete end-to-end  framework that is not constrained by size). 
    • Trusted, verifiable, and secured.  If some one is installing software in their desktop,  they should verify who it came from and then (if needed) trust it to do its job.  If the application needs access to file system, devices, secure stores, sockets, etc.  this is the choice you make at install time; the goal is to trust the application to do its job. You installed the client run-time for that reason. If needed, the run-time can do work to ‘constrain’ the application’s permissions (like Partial Trust). Apps should explicitly declare intent and the permissions they require to run.
    • Easy to deploy/Easy to update/configurable.  I am not aiming for <30 seconds and < 5 MB download like a RIA run-time, but I have to admit Microsoft needs improvements on this.  I am optimistic here:
      • We recently added .NET 3.5 SP1 to Windows Update and hope that over time we get the majority of Windows boxes to 3.5 SP1.
      • With .NET4 we deliver on the vision for client profile.  It will be a 22 MB download, that runs side-by-side with all the other versions of .NET framework, so we will be able to use it on any box (not just clean XP like we have in Client profile with 3.5 SP1). 
        I hope the two combined get us to desktop ubiquity so people can plan a .NET app with out worries about how to install the run-time.
    • Manageable.  When we are talking desktop/enterprise software we quickly get into thousands of users,  controlled versioning, policies, software is centrally distributed , etc..  Desktop software that is installed is easy to manage.  RIA software that can be in caches, user stores, etc. is a bit harder.

    Once you look at the above, it is easy to grasp why today, we do need multiple technologies to address both scenarios. Any one that tells you otherwise is heavily short changing you in one of these two scenarios (usually the desktop).  

    We do need to acknowledge that RIAs need stickiness, and off-line launching, and that is why Silverlight Out Of Browser was created, I call this scenario the “off-line RIA”; and it is very, very different from the “full-trust desktop app”.

    Three more reasons to explain why WPF will be around for a long while: 

    • WPF adoption is going well. We have a lot of partners doing WPF. If you went to PDC, we did a video with just a few of the partners doing WPF, it included Lenovo, HP, AMD, Autodesk, T-Online, Disney, Blockbuster, Roxio, SNCF, SAP, Terra, Cewe, and many others.   These are the types of partners that use WPF to connect with millions of users.  We have equal number of successes in the enterprise with partners who buy lots of Windows licenses and are very important to Microsoft.  We are not walking away from that any time soon.

    Inside Microsoft adoption is also strong;  we see our business platform – the Dynamics team- using it; we have consumer apps like LifeCam and SongSmith, we have office apps like Semblio, our internal IT teams are using it, and our own development division is betting heavily on WPF to create Visual Studio 2010 and Expression Blend.

    Announcement:  Starting next Tuesday (seems like a good day for recurrent series) I will try to start a new “blog series” similar to Tim Sneath’s “Great WPF applications” series; I am not as eloquent as Tim, but I am happy to keep you on the loop on some of the great WPF apps out there. I don’t think we do enough of sharing those successes(again, trees blocking the forest).

    • We are investing into the platform. You did not see that at MIX because most of the announcements were at PDC and we are now in the middle of the .NET 4 release, but you can watch Kevin Gjertadt’s MIX session and hopefully get the message that:
      • WPF will make the most important developer features in Windows 7 accessible to .NET developers.  We are talking Touch!! that is not a small feature. We also have ribbon, taskbar, etc.
      • We continue to improve the fundamentals. Performance and Text are good examples of significant investments in the .NET 4 time-frame. 
      • We thrive to improve deployment so every one can get full .NET Framework applications with much less friction. Details above.
    • WPF is the recommended UI stack in the .NET framework. There are a lot of people that need the full framework for their applications (Workflow, advanced Web services, encrypted stores, Office integration, parallelism, MEF, etc.)  Silverlight is a high-fidelity subset of the framework, and it serves quite well all RIA needs, but we can’t cram the rest of the framework into Silverlight.

    In closing,  WPF will be around a while.  One size does not fit all, today. 

    • It is fair for MIX attendees to wonder about which one to choose, but that is mostly because MIX is a web conference.  These attendees do need off-line, sandboxed RIAs and I am totally psyched that we are able to meet their needs. 
    • For the other customers that need desktop applications that call native Win32 code, access to devices, or integration with desktop and office, then those customers will be able to use WPF.

    The story on the WPF and Silverlight convergence is actually much better than this post discusses because here I aimed at explaining the different scenarios each addresses; stay tuned for Part 3 to discuss the synergies amongst Silverlight and WPF.

  • Jaime Rodriguez

    MIX09 recap series part 1, favorite features and announcements

    • 1 Comments

    I am finally caught up with my family and work stuff , so I want to share my belated recap and my lessons learned from observing and talking to people at MIX09.  Since it is a lot, I partitioned it into three posts:

    Part1: Anything that inspired or excited me.
    Part2: What we could have done (or messaged) better; future for our desktop client.
    Part3: Our mission on the client space: The Microsoft Client Continuum.

    Part 1: The good (or great)!

    IMO, this was the best MIX to date.  Microsoft was finally able to demonstrate and deliver the vision we have been thriving for in the last few years:

    • User Experience and designers were embraced throughout the conference (in part, by credible, recognized thought leaders from Microsoft).
      • Bill Buxton and Deborah Adler keynotes were great.
      • Expression Blend announced their upcoming features, with disruptive, rapid prototyping features like sketch flow, and strong improvements to the fundamentals with behaviors, design-time data,  better import tools, and source control.
    • Internet Explorer 8 is a strong return back to the web standards world. It is compliant, more secure, fast enough,  and innovative: IE8 brings safety and productivity to its users.  I think we are back in the game (and just on time).
    • Silverlight 3 came really strong on all angles:
      • We continue to innovate and lead on media.
      • We are moving at warp speed to catch up to WPF around fundamentals (like element to element data binding, resources, etc.) 
      • We are moving towards the enterprise and already have a great set of features planned for the .NET RIA Services; this is the beginning of a great business platform.
      • To every one’s surprise, we let the cat out of the browser (literally!)

    My favorite features announced through out the conference:

    • Blend behaviors – yes, I know this is not even a new technology feature (we have been able to do them for a while) but I think official support in the tools and pre-canned behaviors in the platform will change how designers create interactivity in applications.   Blend behaviors makes designers more productive and empowers them to do all the things that make me “miss” Triggers when I work on Silverlight.  So I am psyched about behaviors.
      To get familiar with behaviors you should:
    • Sketchflow – has the potential to change conceptual design and end-to-end designer workflow.
      I like the direction on which this is going because it enabled rapid prototyping and potential reuse of these prototypes in the real app.

      To get familiar with sketchflow, you must:
      • Watch Christian Schormann’s Sketchflow session.
      • Wait until ? for us to ship the preview. Sorry!

    • All the Silverlight improvements to get parity with WPF:  Official support for Resource Dictionaries,  Styling improvements, Element to Element binding, etc.   I must say these are probably not crowd favorites either, but they are dear to me because I do write code that goes across both platforms, or often I find myself “missing” a feature that was not there in Silverlight; feature parity between both run-times makes it easier to port code and makes Silverlight better (against other competitors) so it helps us increase our user base.

      To get familiar with these improvements, you need to
    • H.264 Media on Silverlight
      This one is big because it allows us to better serve content providers that had H264 format (mostly due to mobile)  so I had to list, but I have mixed feelings here, I still hear ( and can see from videos I get ) that VC-1 is a better format.  Still I am very excited about the possibilities these offers for us to work with new partners!

    Don’t get me wrong, I was psyched about a lot more features than I mention above, but I had to pick a few top ones. If you want the list of other features that really excited me:

    • Silverlight Out of Browser – is very exciting, but I need to see what people do with it.   I have to say it has the potential to be game changing in the long-run (as we grow it).  I will come back to this one in part2 of the series stay tuned for that.
    • New import features in Blend.  Being able to import Photoshop and illustrator sounds very, very good.   I still need to capture feedback from partners on how good it is; if the quality is good, then this will also be game changing.
    • Perspective 3D in Silverlight.  I am still curious where people take this feature too.  I am sure it will be some where great and I will be looking silly for not saying it was game changing ;)

    OK. that is a very high level of all the “Good stuff” ..   I do have to give a “Thank You!” shout to the audience and partners that attended.  For me and lots of other Microsoft folks, a huge part of MIX are the hallway and meals or party conversations.   It is great to hear what we are doing right, wrong, and what we should do next.

    I also have to throw a shout to the Deborah Adler keynote slot. What an inspiring story.

    Stay tuned for part 2 and part 3 in the series!

  • Jaime Rodriguez

    WPF effects Library running in Silverlight 3

    • 2 Comments

    At MIX last week, we announced that Silverlight 3 supports effects, written in HLSL 2.0 ..  

    If you remember from this previous post, we have a codeplex WPF library with 20+ effects and greater number of  transition effects.  Charles Bissonette, in the Blend team ported the library to Silverlight, and we have now merged it into codeplex.  

    The effects included in this first release are:
    BandedSwirl, Bloom, BrightExtract, ColorKeyAlpha, ColorTone, ContrastAdjust, DirectionalBlur, Embossed, Gloom, GrowablePoissonDiskEffect, InvertColor, LightStreak, Magnify, Monochrome, Pinch, Pixelate, Ripple, Sharpen, SmoothMagnify, Swirl, Tone, Toon, and ZoomBlur

    The transition effects include:
    BandedSwirl, Blings, Blood, CircleReveal, CircleStretch, CircularBlur, CloudReveral, Cloudy, Crumble, Dissolve, DropFade, Fade, LeastBright, LineReveal, MostBright, PixelateIn, PixelateOut, Pixelate, RadialBlur, RadialWiggle, RandomCircleReveal, Ripple, Rotate, Saturate, Shrink, SlideIn, SmoothSwirl, Swirl, Water, Wave.

    If you have Silverlight 3 and want to see the library in action, click here, or in the image below.

    basic 

    To play with the sample app:

    1. Select type of media ( vector or image)
    2. Click on the checkbox by the effect name to apply an effect.
      You can apply multiple effects at same time. 
    3. Tweak the sliders and textboxes to configure the effect. 
      Note: the textboxes save changes on lost focus, so will need to tab out and back in.

    My favorite is the transitions.

    1. Click on the top right button to see the show.  Each 3 seconds the transition will change. The first time they repeat twice so you can see the details, later they get random.


    If you do not have Silverlight 3, Adam Kinney and I recorded an impromptu video for you to see watch the demo with out needing to update your bits to SL3).

    Geeking it out (aka the details):

    • Porting the library was trivial,  there is  probably a total of < 50 #if SILVERLIGHT in the project. They mostly relate to dependency properties ( SL does not do UIPropertyMetadata) and or the use of Vector (not in SL, but Point serves the purpose)..
    • SL effects are not hardware accelerated ( due to security) but it performs pretty well on my machine.. Let us know if you see otherwise.
    • Silverlight does not have VisualBrushes,  but you can use the new WriteableBitmap to create a snapshot of a visual ala  RenderTargetBitmap in WPF so you can create cool transitions.   I did it for the start/stop transitions (though I must say I picked some really funky effects for the transitions).

    The source is in codeplex.
    Packaging will likely change. Right now it is WPF project with SL project linking to the WPF files (the way I keep it in source control) but  I think for easier download, it will become separate zips and I can duplicate the files just for releases (source can still be single shared file).  
    Please check the pre-requisites in codeplex, you will need latest DirectX SDK, .NET 3.5 SP1 ( or VS 2008 SP1),  the Shader Effect build task from WPF Futures and of course SL3 and SL3 tools if you want to run the SL bits.

    More effects pictures:
    One Two

                     Pinch + Inverted colors.                                                                           Embossed

    Enjoy, please report bugs/issues if needed.

  • Jaime Rodriguez

    WPF Discussion, 090313

    • 1 Comments

    You know the drill: raw unformatted, Q&A from our internal discussions.


    Subject: RE: ListBox Binding to IList

    When I bind with my own IList/IEnumerable/INotifyCollectionChanged object, I see WPF wrapping it in a collection view of some sort.  When I create the collection view myself and give it to WPF, it seems not to wrap it in another collection view.  Can you tell me (or point me to code) what’s the magic recipe for determining whether-or-not something gets wrapped in a collection view? 

    Answer:

    Everything that is not already a collection view gets wrapped in a collection view.   The basic rule is:
            IBindingList  gets wrapped by BindingListCollectionView 
            IList gets wrapped by ListCollectionView
            IEnumerable gets wrapped by EnumerableCollectionView.

    EnumerableCollectionView is an internal class that takes a snapshot of the underlying IEnumerable, so yes, it enumerates everything.  You can avoid this by exposing IList.   ListCollectionView only enumerates everything if it has to, usually because you applied sorting, filtering, or grouping. 


    Subject: RenderCapability.Tier edge cases

    Hi,
    We are working on using RenderCapability.Tier in Visual Studio as a way to limit visual candy when being run on a low end machine or over a remote connection. My question is, what happens with this property in edge cases, such as a machine having two graphics cards with different capabilities? Does WPF use the capabilities of the lowest card to set the value? Does the value update dynamically if I move my window from a monitor on one card to a monitor on the other?

    Answer:
    It’s the lowest of all the cards.  Dragging your window from one monitor to another shouldn’t trigger a tier-changed event, nor should the result of your tier-query change.


    Subject: D3DImage on XP
    The documentation on MSDN says this:
    “If you are developing for Windows Vista and Windows XP, test the performance on Windows XP. Running out of video memory on Windows XP is a concern. In addition, D3DImage on Windows XP uses more video memory and bandwidth than Vista WDDM, due to a necessary extra video memory copy. Therefore, you can expect performance to be worse on XP than Vista for the same video hardware.”

    Answer:
    The extra mem copy was required because on Vista with WDDM you can create a shared surface and give the D3DImage that, and WPF will read from the shared surface directly.  On XP there are no shared surfaces so WPF has to copy your D3D device’s surface’s bits to its own D3D device’s surface.


    Subject: Remembering previous windows placement and setting that on next invocation

    I have a simple need of remembering the window placement (size, location etc) on the exit of my WPF app and setting the same on the next start of my app. Looks like this involves calling unmanaged APIs using PInvoke as explained in the article at http://msdn.microsoft.com/en-us/library/aa972163.aspx. This seemed little strange for a simple need of mine. I’m just wondering if there is a better alternative (without use of PInvoke) to satisfy my need?

    Answer:
    Window.RestoreBounds combined with WindowState is your friend.


    I would really like to create a seamless browser-hosted experience, so I went down the ‘web service’ middle tier path as Matt suggested below.  Unfortunately, now I’m receiving this SecurityException when attempting to connect to the web service:

    System.Security.SecurityException: Request for the permission of type 'System.Net.WebPermission, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed.

    The action that failed was:
    Demand
    The type of the first permission that failed was:
    System.Net.WebPermission
    The Zone of the assembly that failed was:
    MyComputer
    It looks as though WebPermission is not allowed for partial trust xbaps either.  Are there any known workarounds for this limitation?  Is silverlight my only option if I don’t want a client app and I don’t want to force users to install a certificate?

    Answer:
    An XBAP is given WebPermission to its site of origin. Your exception is likely due to a mismatch between the XBAP’s launching URL (it’s the host:port part that matters) and the URL you are trying to access the web service at.


    Subject: DrawingImage w/ DynamicResource does not refresh properly when in App.xaml

    DrawingImage in app.xaml…    refers to  brush in app.xaml via DynamicResource  …
    When I update the  Brush in App.xaml    { by loading different skin } my image does not pick up the new  brush…  
    This works fine when these two resources are in Window1.xaml …   
    I know that App.xaml freezes the resources , but I checked and  the brush is frozen… that is OK,  I am not updating it, I am replacing it..   The Drawing Image says it is not frozen..

    Answer:
    This is a bug.  I can’t find anything similar in the bug database;   <>, please open a new bug for this.
    The bug arises when you have two application resources X and Y (i.e. declared in your App.xaml), both of the Freezables, and X contains a dynamic reference to Y.    Also, your main tree contains dynamic references to X (but not to Y, except indirectly through X).   If you change Y, say by replacing it, the main tree is notified but nothing happens, since there are no references to Y.


    Subject: How RenderOptions.CacheHint/CacheInvalidationThresholdMaximum/Minimum works?

    I’m working on a project which uses a lot of ImageBrush in the controls.
    Recently, we found by setting RednerOptions.CacheHint to Cache, and setting CacheInvalidationThresholdMaximum/Minimum can improve the performance, I think this improvement is caused by caching the images. But I want to understand the how these 3 properties works in the code. Can some expert explain this to us?

    Answer:
    RenderOptions.CacheHint helped ImageBrushes? Hmm… maybe. ImageBrushes are already cached but it may cause us to skip resampling the original bitmap. It’s meant for brushes with intermediate surfaces (DrawingBrush and VisualBrush) because if you don’t set any caching hints the contents will be updated every time we render the brush.

    The idea is you set CacheHint to Cache to tell us to try to avoid updating the brush. Now if you scaled the brush way up, it could look terrible and if you scale it down it could look bad as well. So min/max thresholds are relative scales to the initial size of the brush that tell us when to update things again. For example, if you set ThresholdMinimum to .5 and the brush size halves, we’ll update the brush and cache the new result.

  • Jaime Rodriguez

    WPF blogs

    • 2 Comments

    I recently updated and organized my blog subscriptions. Here is a list (and opml) of all the WPF blogs that I subscribe to.

    Please let me know if I missed yours! Also, don't let me fall too far behind on keeping it up-to-date.

    Gracias!  

  • Jaime Rodriguez

    two very promising WPF application frameworks on codeplex

    • 2 Comments

    Catching up on my blog reading, I see two great development frameworks recently posted in Codeplex. Both aim to build clean, testable, loosely coupled WPF applications with separated concerns.  gift

    • Onyx is a framework that aids in the development of WPF applications that follow the Model-View-ViewModel (MVVM) pattern”, by Bill Kempf

    • "Designed to aid in the development of WPF and Silverlight applications, Caliburn implements a variety of UI patterns for solving real-world problems. Patterns that are enabled by the framework include MVC, MVP, Presentation Model (MVVM), Commands and Application Controller” , by Rob Eisenberg 
    Check them out, share your feedback, use them, join and contribute (if you rejoice in that kinda thing)!

    I am really looking forward to diving into these and to see where the community takes them!

  • Jaime Rodriguez

    WPF Discussion,090228

    • 1 Comments

    Inside Microsoft, we have our own version of “forums” or “discussion groups” .. 
    Lots of great questions and knowledge get fleshed out in these conversations.   Below is a brief (edited) version of the questions that caught my attention in the last two days. Going forward, I will try to watch these discussions closer and post the juicy ones a couple of times a month (it will always be on friday or saturday, so check for them on mondays).


    Subject: XAML State of the nation

    Rob Relyea says:   Just blogged this update to the community…   

    [It is a very transparent, and relevant update, thanks Rob! ]


    Subject: RE: Is there a way to display first frame of video in MediaElement when loaded?

    I used MediaElement to display video. If I set LoadedBehavior as anything other than Play, MediaElement cannot display the first frame of the video but a black screen. If I set it to Play, video will start playing right away. Is there a way to only display the first frame of the video but not playing video when loaded?

    Answer:
    Set Scrubbing to TRUE, Pause and Seek to zero. Note, the first frame IS black for quite a few videos. (Fade from black is pretty common).


    Subject: Media Element Memory Leak?

    I have a very media intensive application developed in WPF. It makes extensive use of MediaElements. What I have been observing is memory leak in my application under very specific conditions. I’m using stream media off of the internet like CNN. When the network is running great all is wonderful. If the network is not available, I don’t get any content but the application still runs with no memory problems. However if the net work is spotty and I’m having issues getting the streams my memory begins to build up until the application runs out of memory.

    I know about this spotty condition as I have other services being called that fail due to network timeouts. I’ve isolated these and they don’t seem to be the issue.

    Any ideas or suggestions?

    BTW: I do destroy and create new media elements during the course of the application… It’s almost like the media element even though its removed is still trying to spool the stream after I’ve removed a reference to it. So its just hanging out taking up memory as it tries to spool that stream…


    Answer:

    You might be hitting the handle leak described in bug XXXX . A section handle is leaked when you create a single instance of MediaElement and free it up without having another MediaElement anywhere else in the app. “Freeing up” a MediaElement includes calling Close(), so maybe it’s also triggering every time you lose the stream. The workaround is to put a second MediaElement anywhere in the app, so that you never end up destroying the only remaining instance of MediaElement. Try that out and see if it works for you.

    Follow-up:

    There are also a few known leaks in WMP which MediaElement uses:
    http://support.microsoft.com/kb/933245
    http://support.microsoft.com/kb/959260
    http://support.microsoft.com/kb/892313


    Subject: Overlapped drawings and blending

    Hi,

    I have some rectangles that are being drawn in a call to OnRender.  They are all the same height and are being drawn horizontally.  There are times when rectangles have one or more overlapping regions with other rectangles.  Where the rectangles overlap they sometime appear taller.  I am guessing this is due to some blending that is happening on the top and bottom edges of the rectangles behind the scenes.  I tried turning off Aliasing but I cannot afford the side effects it produced since I use transforms and scaling to move these.  Is there an alternative to drawing these on a bitmap and changing the ScalingMode?

    Answer:
    If these were top-level FrameworkElements, you could use SnapsToDevicePixels (http://msdn.microsoft.com/en-us/library/system.windows.uielement.snapstodevicepixels.aspx), which is implemented in terms of DrawingContext.PushGuidelineSet (http://msdn.microsoft.com/en-us/library/system.windows.media.drawingcontext.pushguidelineset.aspx).  Since you're using the DrawingContext directly, I'd encourage you to try this too.  There's more info here as well: http://msdn.microsoft.com/en-us/library/system.windows.media.guidelineset.aspx (with pictures!).  Used correctly, this should address the issue for all axis-aligned objects regardless of DPI/scale/size/sub-pixel position.


    Subject: Which measure points to take for GUI response times

    My customer wants to use WPF’s internal measure points (not sure what those are?) to get timings from their UI responsiveness. They would like to answer some basic questions like “what is the total time a certain window or control takes from a user click to the time when it has rendered completely on the screen”?

    Apparently there are a lot of these measure points, but they fail to find the ones that are relevant. Do we have any guidance on which measurements to take and which questions they can help answer?

    Answer:
    http://windowsclient.net/wpf/white-papers/event-tracing-wpf.aspx


    Follow-up:
    Thanks, that looks like an interesting list, and from reading into it I assume that the WClientLayout event is the one they would be interested in to know the total rendering time of an element as I mentioned below?

    >>>
    Well, there are many things to keep  in mind.  WPF has a UI thread and a render thread.  The render thread processes “batches” of updates per frame.  So there are lots of events to consider.

    the event raised when rendering has completed is:

    WClientUceNotifyPresent


    Subject: changing icon for Windows app installed by ClickOnce

    …is there a way to change an icon for an app deployed by ClickOnce, without having to track down the actual .exe location, creating a shortcut to that, then setting the icon on the Shortcut tab?  MSSolve (CRM app for CSS) was deployed this week and no icon was specified in the package, so I'd like to use something other than the default "white square" icon that it came with.


    Answer:
    It is possible to create a custom icon for your application that is deployed by ClickOnce.  You can set the following in description section in your application manifest. ClickOnce will use your icon instead of the default icon in the Start Menu shortcut.
    <description iconFile="sample.ico" />
    where sample.ico is your icon file which is also included in the application manifest.


  • Jaime Rodriguez

    WPF Training Resources, March Edition

    • 1 Comments

    Karl and I have gotten a good number of questions about the MVVM training.  Here are the most common answers:

    • The training was not recorded; we will do that later (probably after tour below )
    • We are looking to repeat it, in April/May, multiple locations in the US.  The format will change slightly, it will be two-day (first day is WPF fundamentals, still aimed at LOB developers, second day is MVVM).  
    • Once we have figured out dates & locations we will announce it via blog posts.  Registration should be easy and current plan is for it to be free.
    • Here is the HOL lab for the MVVM training: C# versionVB version.

    While we figure details on the above training, below are some WPF training resources.

    For free online training (at your own pace): 3 days WPF bootcamp from MIX University.

    For instructor lead, upcoming WPF trainings and events for month of March.
    If you are interested in attending these, feel free to follow the registration instructions below. All of the events are free; as you can see there are some amazing trainers delivering these sessions.   

    Date Location Event description Trainer Registration
    3/4 to 3/5 Washington,DC XamlFest (WPF + SL, intro) Joh Pelak RSVP via email
    3/4 to 3/6 Mississauga, ON Canada 3-day WPF training (intro) Charles Petzold Metro, see below
    3/4 to 3/6 Irving, TX 3-day WPF training(intro) Ian Bowler Metro, see below
    3/9 to 3/11 Segrate, Italy 3-day WPF training(intro)   Metro, see below
    3/11 to 3/13 London, UK 3-day WPF training(intro)   Metro, see below
    3/11 to 3/13 Santiago, Chile 3-day WPF training(intro) Robby Ingebretsen Metro, see below
    3/17 to 3/19 Vedbaek, Denmark 3-day WPF training(intro)   Metro, see below
    3/31 to 4/2 Melbourne, Australia 3-day WPF training(intro) Josh Reuben Metro, see below
    3/31 to 4/2 London, UK 3-day WPF training(intro)   Metro, see below
    4/14 and 4/15 St. Paul, MN XamlFest (WPF +SL ) intro John Pelak RSVP via email
    4/29 and 4/30 Chicago, IL XamlFest (WPF +SL ) intro John Pelak RSVP via email

    For Metro trainings, the registration is private, feel free to email me directly and I will forward the details.   

    If none of the above suits your timeline or location,  please try one of our training partners: Pluralsight, Developmentor, Wintellect, etc. their trainings are often longer and deeper.

    If you know of more events, let me know..  I am sure there are many others.. apologies if I missed some one’s event..

  • Jaime Rodriguez

    Design-time data in Expression Blend

    • 4 Comments

    Well- behaved, unobtrusive design-time data is essential for designers to create high-fidelity data templates and get a comprehensive view of the scene they are designing. If you agree, here is a must read on the common approaches to implementing design-time data inside blend (and Cider); the write-up covers:

    • The common ways to use ObjectDataProvider for design-time data. Pros & cons for each.
    • My favorite way to do design-time data via an Attached behavior..

    The source is available here.  The paper is here on  HTMLXPS, and DOCX.

    Let me know if I missed any thing..

  • Jaime Rodriguez

    Using Uris in Expression Blend

    • 2 Comments

    Last week, Unni and Pete explained to me how Blend resolves Uris. In this post, I will attempt to explain the details and the possible solution.  

    Details:
    We already knew that at design-time, Blend loads your window, usercontrols, or what every you are designing, in its main process (and main AppDomain). 
    In the default scenario, this would imply that all Uris will not work (since they resolve relative to Blend’s application) but there is some special handling in Blend to handle Uris in XAML. Blend reads the XAML and alters the Uri references so that they resolve relative to the file:// path of the designed application, instead of relative to Blend’s application. 

    For the most part, Blend does a good job and from XAML your Uris will work fine, but you will notice issues when you are resolving Uris that are not in the parsed XAML:

    • If you have design-time data, and the Uri’s are coming from data bindings, then blend can not intercept these and fix them.
    • If your Uris are coming from code that is executing while in design-time then Blend has no way of fixing them and your code is likely going to throw an exception or not resolve.

    Solution:

    As you already know, I like absolute Uris and the pack syntax; so I am going to stick with it, but now I have to emphasize that you use the full syntax (including the component part) on the Uri.  If you do this,  Blend seems to resolve very well on most scenarios, including code and bindings!!

    I will say it again, full Uri including component part. For example:

    • pack://application:,,,/Images/happyface.png  is wrong.  This will work from XAML, but not from code.  It needs to be
    • pack://application:,,,/WpfApplication6;component/Images/happyface.png    If you do this, Blend resolves well all the time!

    Note: I labeled it possible solution because I am aware that not every one likes the full pack syntax. It can be cumbersome. I also have to explain, that not every one needs this solution, you only need it when the Uris come from code and are needed at design-time (in Blend). Mixing and matching Uris might be a good compromise.  

    Want to see more?
    This sample shows all kinds of different paths to resolve an image.
    As you can see, at design-time, the binding ones and the ones that come from code, do work when using a full path. 

    Blend, design-time Run-time
    image   image

    Happy blending!!

  • Jaime Rodriguez

    Hiking Mt. Avalon at MIX09…

    • 3 Comments

    Planning for our WPF workshop at MIX 09 is already in full swing at hour 2… and I am psyched about the speakers  we’ve already recruited:  John Gossman (WPF and Silverlight architect)  and  Jonathan Russ (Identitymine rock star developer and exWPF team member from the Avalon days).     

    We now have the authorities on architecture (john), developers (jonathan), designer/integrator (robby), and getting drinks (jaime) covered. We hope to have another designer confirmed by end of the week.  

    On agenda, we have to complete the team before we commit, but in case you need to change your reservations or register for the session, here is a quick draft from a 30 minute lunch w/ Robby.  Expect it to grow!

    The four ‘axes’ into the hike are going to be: Guidance, Tips, Patterns, and Collab…  

    image 

    If you are coming, or have advise on a tough WPF topic, please let us know what we absolutely must cover…

    While I am hyping our session,  I should also share that the morning workshops are very, very good.  Robby has a ‘Design fundamentals for developers’ and  Adam Kinney has a ‘Rosetta Stone, from Flash to XAML’ session.

    Don’t miss out!! If you need to convince your boss to let you come, tell him this is going to save you days (or weeks) later in your project; we hope to give you the map to the mountain (and share the best tips & tricks)..

    C U @Mix09..

  • Jaime Rodriguez

    M-V-VM training day sample application and decks

    • 14 Comments

    During the M-V-VM training (last saturday) with Karl Shifflett I showed and referred often to this Southridge application below..
    The app is not very clean(when it comes to resources and styles in particular) but it is a fairly good ViewModel example, and it served well to illustrate a few of the points we made at the training (both good and bad practices).  So I am sharing it (as promised).   

    The application consists of three views sharing one ViewModel around real-estate data (called MainViewModel).

    The application's chrome includes a ribbon that drives all the Viewmodel via its filtering functionality.  The two filter commands that work are Bathrooms and bedrooms [if you change the selection for these, the results on the views should filter].

    image 

    I purposedly did not make the main window with the ribbon a view because I often run into applications that transition views so I wanted to show the concept of having a constant element in the chrome.   The ribbon is functional ( you can see its resize behavior).
    The checkbox columns are bound to the MainViewModel, and drive the columns that show up in the Search view (below).

    The views
    Again, the views are the results for the search from the criteria in the ribbon. 

    image image

    Both of these views are 100% XAML. 

    The grid is very functional, sort, selection, etc.   I call it SearchView.
    The map is simply a Listbox with a datatemplate and a tooltip on the ListBoxItems. I need to add more to that UI.  I call it the MapView :)
    You navigate to the map view, by either clicking on the map icon on the left hand side of any row of the data grid, or by clicking on the Map Ribbon button on the Search Results tab. 
    The full details of course include an OpenMap Command exposed in the MainViewModel that does the work.

    To go back to SearchView (from any view), just click on the Search tabs, and it automatically goes back.  The way that happens is through an attached behavior in the RibbonTab:

    <r:RibbonTab Name="SearchTab" Label="Search Criteria" view:RibbonTabSelectedBehavior.SelectionChanged="{Binding SearchSelectedCommand}" 

    This is a standard attached behavior that delegates the event and 'forwards' it the SearchSelectedCommand on the MainViewModel.  You can see the implementation on the RibbonTabSelectedBehavior class.


    There is another totally different View, called Profile.. 

    image

    This view demonstrates data validation using IDataErrorInfo. It has an InfoTextBox (from Kevin Moore's bag-o-tricks) and shows the fields that are invalid in red.

    The validation is trivial, mostly checks for empty strings on all fields, except zipcode, around ZipCode it enforces the 5 digits or 9 digits with a dash format for US Zipcodes.

    [For details, check the Profile class] in XMLData project. ]

    You can see how the "Save Profile" command is wired to only be enabled when the data is valid.

    The Profile view purposedly contains a "PreferencesEditor" usercontrol that is not a view itself; it takes data context and drives its UI from it, but does not have full view functionality (again to illustrate a point: not every thing is a view).

    The profile window has both a DataTemplate ( for everything in "Contact information"). 

    The listboxes in Location are interesting because they State is populated with read-only data (I call it meta-data) that is not coming from the view model,  but the views are bound to the Viewmodel when selection happens (county is driven by the selection on State).   Be aware that the data is not big and some states (e.g. CA) might not have valid data. Try WA to see it the way I see it.

     

    The final screen is the Listing Details screen. This is a modal window that shows Listing details. Nothing too exciting here but it is a wired view model, including the Make appointment button. You may notice that the "Neighborhood" data template in this view is the exact same data template from the Tooltip on the map.   yes, I am lazy and I drive reuse, that is why viewmodel is my friend.

    The Listbox has a very "view specific" behavior implemented by 3 lines of code behind, it is used to implement selection when mouse enteimagers a listboxitem. I purposedly left it as is, though I am sure some M-V-VM purist will tell me I should have implemented it as an attached behavior. I chose not to because I did not want the viewmodel to manipulate the view on a quirk like this one. The view can self-contain the behavior and yes, if I try to move the code to Silverlight it will need the same 3 liner. I was OK with that.  I felt it was equally bad to have the ViewModel be listening for view events and "manipulate the view" directly (which I would have needed).

    At last, there is one class that keeps it all together, I called it the ViewManager. This is an over-simplistic implementation of a Presenter for the views that handles transitions across the views.  The views register with the viewmanager as they are instantiated, and the ViewModel can trigger call into the ViewManager ( a singleton) of course to trigger transitions across views. The viewManager itself can have a ViewModel if needed; in this case I did not use it, but in other apps I have used it.

    That is it, if you were at the class I hope you remember this.  If you were not, then maybe looking at the deck might help, though I must say the class was quite driven by example, so the slides are a bit presentation-zen-like. Please try the notes for a bit more context and drop me a comment or email if that is not cutting it.

    At last, thanks to all those that attended the class.  It was a lot of fun, and I really enjoyed meeting all of you.
    Thanks also to Matthias & Bruno & Karl for puttting it together and for inviting me. 

    Presentation (ppt deck) is here.   Code is here.  The code requires the WPF toolkit, all assemblies needed should be included in the project but if you get a compilation error, try getting the toolkit and the ribbon from codeplex

    [Disclaimer again, the code needs some heavy scrubbing on the UI and resources; also I had to take out the data that I normally use, so if you see #if SQLCE, simply ignore these.  I replaced all the data with an XML file (for easy tweaking). It is not real data, so don't be surprised when you see a Seatttle address in an Issaquah neighborhood.  I merely invented the data on the fly].

  • Jaime Rodriguez

    Styling Microsoft’s WPF datagrid

    • 9 Comments

    Microsoft’s WPF datagrid has a lot of properties and styles you can tweak to get it looking right (if you are a designer). 
    Below, find my cheat sheet to styling the grid.   It is not 100% comprehensive but it gets you far and has a few very useful tips & gotchas.

    At the highest level in the DataGrid , you can change the look & feel by setting some of these:

    Property Type Values Default
    AlternatingRowBackground Brush Any Brush Null
    Background Brush Any Brush Theme default
    ColumnHeaderHeight Double 0 to any positive double NaN
    ColumnHeaderStyle Style Any Style Null
    ColumnWidth DataGridLength 0 to any positive double, Auto, *, SizeToCells, SizeToHeader SizeToHeader
    HeadersVisibility DataGridHeadersVisibility All, Row, Column, None All
    MaxColumnWidth Double 0 to any positive double Positive Infinity
    MaxRowHeight Double 0 to any positive double Positive Infinity
    MinColumnWidth Double 0 to any positive double 20
    MinRowHeight Double 0 to any positive double 0
    RowBackground Brush Any Brush Theme default
    RowDetailsVisibilityMode DataGridRowDetailsVisibilityMode Visible, VisibleWhenSelected, Collapsed VisibleWhenSelected
    RowHeadersWidth Double 0 to any positive double NaN
    RowHeight Double 0 to any positive double NaN
    AlternationCount int 2+ coerced to 2
    GridLinesVisibility DataGridGridLinesVisibility All, Horizontal, Vertical, None All
    HorizontalGridLinesBrush Brush Any Brush Black(via metadata)
    VerticalGridLinesBrush Brush Any Brush Black(via metadata)
    ItemTemplate DataTemplate Any DataTemplate Null
    RowDetailsTemplate DataTemplate Any DataTemplate Null
    CellStyle Style Any Style Null
    ItemContainerStyle Style Any Style Null
    RowHeaderStyle Style Any Style Null
    RowStyle Style Any Style Null
    Style Style Any Style Null
    Template ControlTemplate ControlTemplate TargetType=Datagrid Null

     

     

    Here, you can see a visual representation for a few of these properties (the visual is not all inclusive); this will give you an idea of what this article will cover.

    DataGridVisually2

     

    Backgrounds:
    The interesting part are the relationships amongst the backgrounds:

    • Background – sets the whole data grid’s background.  Notice it can be any brush, solid and gradients is obvious, but why not a DrawingBrush like the bear above ( which you can see if you squint hard, it has Opacity =0.1)
    • RowBackground  and AlternatingRowBackground  set the background for a row and alternating row. 
      Both of these have a higher z-order than DataGrid’s background of course, which means you can get visual composition w/ the grid’s background. 
      Notice that the default color for RowBackground is theme based (and default value is opaque); your DataGrid’s background will not be visible unless you override these row backgrounds to be partially transparent.
    • AlternationCount is the total number of styles or colors that will be used for the rows.  This number is one-index based (meaning count starts at 1, not 0).
      • If you set AlternationCount > 2, your rows from 3rd row to AlternationCount will be assigned the default background brush value (from the theme).
      • The way to set the different backgrounds or styles for each row based on AlternationCount is by overriding the style for your DataGridRow and triggering based on AlternationIndex, which is actually zero-index based.  
      • If you set the AlternatingRowBackground brush, it will be assigned to the rows where the ( rownumber%AlternationIdex ) == 1

    Here is an example of overriding RowStyle to tweak background based on AlternationIndex:

     <Style x:Key="DataGridDemoRowStyle"  
           TargetType="{x:Type Custom:DataGridRow}">
        <Style.Triggers>
            <Trigger Property="AlternationIndex" Value="2" >
                <Setter Property="Background" Value="{StaticResource RowBackgroundAlternationIndex2Brush}" />
            </Trigger>
            <Trigger Property="AlternationIndex" Value="3">
                <Setter Property="Background" Value="{StaticResource RowBackgroundAlternationIndex3Brush}" />
            </Trigger>
        </Style.Triggers>
    </Style> 

    Notice that, on purpose, I only override AlternationIndex = 2,3.  For AlternationIndex=0, it uses RowBackground.
    For AlternationIndex = 1, it uses AlternatingRowBackground from the datagrid. 
     

     

    Datagrid Column Headers

    I usually customize the header on a data grid to accomplish one of two tasks:

    • Tweak the background of the headers, including triggers for hovers, selected, etc.
    • Tweak the Control template of the header, mostly because the default style to show Sorting is on top of ColumnHeader and I like it on the side.

    My instinct was that customizing the header’s background would be a simple style override. Here is my try:

    <Style x:Key="DataGridColumnHeaderStyle" TargetType="{x:Type Custom:DataGridColumnHeader}"  >
        <Setter Property="Background" Value="#88800080" />
            <Setter Property="Foreground" Value="White" /> 
            <Style.Triggers>
            <Trigger Property="SortDirection" Value="{x:Null}">
                <Setter Property="Background" Value="{DynamicResource DataGridHeaderBackgroundBrush}" />
                <Setter Property="BorderBrush"  Value="Transparent" />
            </Trigger>
            <MultiTrigger>
                <MultiTrigger.Conditions>
                    <Condition Property="IsMouseOver" Value="True" />
                    <Condition Property="SortDirection" Value="{x:Null}" />
                </MultiTrigger.Conditions>
                <Setter Property="Background" Value="{StaticResource DataGridHeaderMouseOverBackgroundBrush}" />
                <Setter Property="BorderBrush" Value="{StaticResource DataGridHeaderBorderBrush}" />
            </MultiTrigger>
    
            <MultiTrigger>
                <MultiTrigger.Conditions>
                    <Condition Property="IsMouseOver" Value="true" />
                    <Condition Property="SortDirection" Value="{x:Null}" />
                </MultiTrigger.Conditions>
                <Setter Property="Background" Value="{StaticResource DataGridHeaderMouseOverBackgroundBrush}" />
                <Setter Property="BorderBrush" Value="{StaticResource DataGridHeaderBorderBrush}" />
            </MultiTrigger>
            <Trigger Property="SortDirection" Value="Ascending">
                <Setter Property="Background" Value="{StaticResource DataGridHeaderSortedBackgroundBrush}" />
            </Trigger>
            <Trigger Property="SortDirection" Value="Descending">
                <Setter Property="Background" Value="{StaticResource DataGridHeaderSortedBackgroundBrush}" />
            </Trigger>
        </Style.Triggers>
    </Style>

    If you run the sample code against that style, you will notice that the Sort direction arrow that is shown in the default style for the Datagrid disappeared'; the reason for it is that DataGridColumnHeader uses DataGridHeaderBorder in its template;  DataGridHeaderBorder is a kind of smart Border that checks if you set a Background and if you did, it behaves like a Border; if you did not set a Background, it then acts smartly and does the code to render the triangle indicator for sort. 

    If you do want sort direction arrows, and a different background you should just override the template and use a regular Border or what ever you want for the background.  Overriding the template is not too hard, here is an example:

    <Style x:Key="DatagridColumnHeaderCustomTemplateStyle" 
             TargetType="{x:Type Custom:DataGridColumnHeader}">
          <Setter Property="SnapsToDevicePixels" Value="True" />
          <Setter Property="MinWidth" Value="0" />
          <Setter Property="MinHeight" Value="28" />
          <Setter Property="Foreground" Value="White" />
          <Setter Property="Cursor" Value="Hand" />
          <Setter Property="Template">
              <Setter.Value>
                  <ControlTemplate TargetType="{x:Type Custom:DataGridColumnHeader}">
                      <Grid>
                          <Grid.ColumnDefinitions>
                              <ColumnDefinition Width="*" />
                              <ColumnDefinition Width="Auto" />
                          </Grid.ColumnDefinitions>
                          <Border x:Name="BackgroundBorder" BorderThickness="0,1,0,1" 
                                  Background="{StaticResource DataGridHeaderSortedBackgroundBrush}" 
                                  BorderBrush="{StaticResource DataGridHeaderSortedBorderBrush}" 
                                  Grid.ColumnSpan="2" />
                          <ContentPresenter Margin="6,3,6,3" VerticalAlignment="Center" />
                          <Path x:Name="SortArrow" Visibility="Collapsed" Data="M0,0 L1,0 0.5,1 z" Stretch="Fill" 
                                Grid.Column="1" Width="8" Height="6" Fill="White" Margin="0,0,8,0" 
                                VerticalAlignment="Center" RenderTransformOrigin="0.5,0.4" />
                          <Rectangle Width="1" Fill="#AAC377" HorizontalAlignment="Right" Grid.ColumnSpan="2" />
    
                          <Rectangle Width="1" Margin="0,0,1,0" Fill="#425B10" 
                                     HorizontalAlignment="Right" Grid.ColumnSpan="2" />
                          <Thumb x:Name="PART_LeftHeaderGripper" HorizontalAlignment="Left" 
                                 Style="{StaticResource ColumnHeaderGripperStyle}"/>
                          <Thumb x:Name="PART_RightHeaderGripper" HorizontalAlignment="Right" 
                                 Style="{StaticResource ColumnHeaderGripperStyle}"/>
                      </Grid>
                      <ControlTemplate.Triggers>
                          <Trigger Property="SortDirection" Value="{x:Null}">
                              <Setter TargetName="BackgroundBorder" Property="Background" 
                                      Value="{DynamicResource DataGridHeaderBackgroundBrush}" />
                              <Setter TargetName="BackgroundBorder" Property="BorderBrush"  
                                      Value="Transparent" />
                          </Trigger>
                          <MultiTrigger>
                              <MultiTrigger.Conditions>
                                  <Condition Property="IsMouseOver" Value="True" />
                                  <Condition Property="SortDirection" Value="{x:Null}" />
                              </MultiTrigger.Conditions>
                              <Setter Property="Background" TargetName="BackgroundBorder" 
                                      Value="{StaticResource DataGridHeaderMouseOverBackgroundBrush}" />
                              <Setter Property="BorderBrush" TargetName="BackgroundBorder" 
                                      Value="{StaticResource DataGridHeaderBorderBrush}" />
                          </MultiTrigger>
                          <MultiTrigger>
                              <MultiTrigger.Conditions>
                                  <Condition Property="IsMouseOver" Value="true" />
                                  <Condition Property="SortDirection" Value="{x:Null}" />
                              </MultiTrigger.Conditions>
                              <Setter TargetName="BackgroundBorder" Property="Background" 
                                      Value="{StaticResource DataGridHeaderMouseOverBackgroundBrush}" />
                              <Setter TargetName="BackgroundBorder" Property="BorderBrush" 
                                      Value="{StaticResource DataGridHeaderBorderBrush}" />
                          </MultiTrigger>
    
                          <Trigger Property="SortDirection" Value="Ascending">
                              <Setter TargetName="SortArrow" Property="Visibility" Value="Visible" />
                              <Setter TargetName="SortArrow" Property="RenderTransform">
                                  <Setter.Value>
                                      <RotateTransform Angle="180" />
                                  </Setter.Value>
                              </Setter>
                          </Trigger>
                          <Trigger Property="SortDirection" Value="Descending">
                              <Setter TargetName="SortArrow" Property="Visibility" Value="Visible" />
                          </Trigger>
                          <Trigger Property="DisplayIndex" Value="0">
                              <Setter Property="Visibility" Value="Collapsed" 
                                      TargetName="PART_LeftHeaderGripper"></Setter>
                          </Trigger>
                      </ControlTemplate.Triggers>
                  </ControlTemplate>
              </Setter.Value>
          </Setter>
      </Style>

    A few things to notice above:  I replaced DataGridHeaderBorder for a normal border; I added a little “triangle” for sort direction, and then transform it (or flip it) based on SortDirection.

     

    DataGrid Row Headers

    For me, these are the most common ‘tweaks’ to RowHeader.

    • Tweaking the width (as the default is too small)
    • Tweaking the background to match my theme.
    • Implementing row selection by clicking on the row header; this feature does not come out of the box.
    • Error handling happens in the RowHeader

    My very first try when looking at the API was to set Row Header Width via styles.  Later on, I realized that DataGrid exposed the RowHeaderWidth property directly so I am now using that instead.  This is a trivial property setter.

    For tweaking  the background,  I first tried setting a the RowHeader style property in the datagrid. The basic style I tried looked like this: 

     <Style x:Key="DataGridRowHeaderBackgroundStyle" TargetType="{x:Type Custom:DataGridRowHeader}">
            <Setter Property="Background" Value="Gray" />
        </Style>
    

     

    It works, but similar to ColumnHeaders I lost functionality.  At run-time, it looked like this:

    RowHeaderBackgroundOnly

    As you will notice, it lost the row DataGridLines that separates each row; there are no hovers, etc. 
    I then proceeded to override the template.  The change was actually trivial, I noticed that DataGridHeaderBorder defaults back to the rendering for it’s base class (Border),  so this mostly implied setting a BorderThickness on it to fake the grid’s row separators, and binding the color to the DataGrid’s HorizontalGridLinesBrush.. 

    Here is the template that I created for the DataGridRowHeader.. (and below the explanation on a few extra gotchas).

    <Stylex:Key="{x:TypeCustom:DataGridRowHeader}"TargetType="{x:TypeCustom:DataGridRowHeader}">
        <
    SetterProperty="Background"Value="{StaticResource RowHeaderBackgroundBrush}" />     
        <
    SetterProperty="Template">
            <
    Setter.Value>
                <
    ControlTemplate TargetType="{x:TypeCustom:DataGridRowHeader}">
                    <
    Grid>                       
                        <
    Custom:DataGridHeaderBorder IsSelected="{TemplateBinding IsRowSelected}"
                                    
    IsHovered ="{TemplateBinding IsMouseOver}"
                                    
    IsPressed="{TemplateBinding IsPressed}"
                                    
    BorderBrush="{Binding RelativeSource={RelativeSource AncestorType={x:Type Custom:DataGrid}},
                                       
    Path=HorizontalGridLinesBrush}"
                                    
    Background="{TemplateBinding Background}"                                    
                                    
    BorderThickness="0,1,0,0"
                                    
    Padding ="{TemplateBinding Padding}"
                                    
    Orientation="Horizontal"
                                    
    SeparatorVisibility="{TemplateBinding SeparatorVisibility}"
                                    
    SeparatorBrush="{TemplateBinding SeparatorBrush}" Margin="0,-1,0,0">

                            <
    StackPanel Orientation="Horizontal">
                                <
    ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                                 
    VerticalAlignment="Center"/>
                                <
    Control SnapsToDevicePixels="false"
                          
    Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type Custom:DataGridRow}},
                                   
    Path=(Validation.HasError),
                          
    Converter={StaticResource bool2VisibilityConverter}}"
                          
    Template="{Binding RelativeSource={RelativeSource AncestorType={x:Type Custom:DataGridRow}},
                                   
    Path=ValidationErrorTemplate}" />
                            </
    StackPanel>
                        </
    Custom:DataGridHeaderBorder>
                        <
    Thumb x:Name="PART_TopHeaderGripper"
                  
    VerticalAlignment="Top" Height="3"
                  
    Style="{StaticResource RowHeaderGripperStyle}"/>
                        <
    Thumb x:Name="PART_BottomHeaderGripper"
                  
    VerticalAlignment="Bottom" Height="3"
                  
    Style="{StaticResource RowHeaderGripperStyle}"/>
                    </
    Grid>

                    <
    ControlTemplate.Triggers>                       
                        <
    Trigger Property="IsMouseOver" Value="True">
                            <
    Setter Property="Background" Value="{StaticResource RowHeaderIsMouseOverBrush}" />
                        </
    Trigger>
                        <
    Trigger Property="IsRowSelected" Value="True">
                            <
    Setter Property="Background" Value="{StaticResource RowBackgroundSelectedBrush}" />
                        </
    Trigger>
                    </
    ControlTemplate.Triggers>
                </
    ControlTemplate>
            </
    Setter.Value>
        </
    Setter>
    </
    Style>

     

    The interesting changes were:

    • I had to use an implicit style.  Though the DataGrid does have have RowHeaderStyle property, it some how did not work for me; which is weird because RowHeaderStyle worked fine when I used style that did not override the template.
    • The BorderThickness of DataGridHeaderBorder is set to 0,1,0,0..  and that makes it draw the equivalent of a GridLine,  I offseted the Margin by 0,-1,0,0  to make sure this aligned with the DataGridRow GridLines.
    • BorderBrush in DataGridHeaderBorder is bound to the DataGrid’s HorizontalGridLinesBrush.
    • I went ahead and added a trigger for IsRowSelected, bound to a local Brush in the dictionary. So now the RowHeader will display its Selected state visually.
    • I added a trigger for IsMouseOver,   it is just ‘expected behavior’.
    • I set a Height of Size 3 to the Thumbs used for the grippers that resize the row. The reason I did this is because I like to be able to double click on a header and have it select the whole Row; this functionality is implemented in the datagrid,  but the Thumbs are so big that they get on the way of trying to click in the RowHeader.  A size of 2 or 3 for the Thumbs seems to do fine for dragging and leaves enough room for clicking on the RowHeader to select row.
    • Another interesting feature I learned when playing with RowHeader was that if you double  click in the Thumbs that resize the row, it goes back to its original size.  Nice touch (that I did not know about).

    Moving on to the task of reporting errors in the RowHeader,  I did not tweak the DataGridRowHeader at all to do any thing related to errors.  I did it all via the DataGrid’s ErrorTemplate property to point to ErrorTemplate2 in my resource dictionary.

    <ControlTemplate x:Key="ErrorTemplate2">
           <Grid  MinWidth="20" MinHeight="20">
                <Rectangle Fill="{StaticResource ErrorTemplateBrush}" />      
           </Grid> 
    </ControlTemplate>
    

     

    <digression>
    I do not like that ErrorTemplate is a ControlTemplate. In my opinion it should be a DataTemplate with access to the DatagridRow’s context and the DatagridRow’s error collection.   As a ‘workaround you can try to pass this into the control yourself by tweaking the  RowHeaderTemplate, and passing the DataContext into the control that acts as placeholder for ErrorTemplate, like this:

    <Control SnapsToDevicePixels="false"
    Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type Custom:DataGridRow}}, 
            Path=(Validation.HasError), 
    Converter={StaticResource bool2VisibilityConverter}}"
    Template="{Binding RelativeSource={RelativeSource AncestorType={x:Type Custom:DataGridRow}}, 
            Path=ValidationErrorTemplate}" 
                     DataContext="{Binding
                        RelativeSource={RelativeSource  AncestorType={x:Type Custom:DataGridRow}},
                        Path=(Validation.Errors)[0].ErrorContent }"                                             
                        >

    You can then tweak the ErrorTemplate datagrid with a tooltip:

    <ControlTemplate x:Key="ErrorTemplate2">
          <Grid  MinWidth="20" MinHeight="20" ToolTip="{Binding}">
               <Rectangle Fill="{StaticResource ErrorTemplateBrush}" >               
               </Rectangle>             
           </Grid> 
    </ControlTemplate>

    and get something more helpful error message, like this:

    ToolTipError

    </digression>

     

    Cell Styles

    By default the DataGrid’s cell show a themed, blue background when selected (see image in closing thoughts below), I did not like that, so I used DataGrid’s CellStyle to take care of that. Override the default template and remove the triggers for selection:

    <Style x:Key="DataGridCellStyle" TargetType="{x:Type Custom:DataGridCell}">
            <Setter Property="Background" Value="Transparent" />
            <Setter Property="BorderBrush" Value="Transparent" />
            <Setter Property="BorderThickness" Value="1" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Custom:DataGridCell}">
                        <Border Background="Transparent" 
                      BorderBrush="{TemplateBinding BorderBrush}"  
                      BorderThickness="0" 
                      SnapsToDevicePixels="True">
                            <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

     

    RowDetailsTemplate

    The RowDetails Template is displayed when a row is selected. It is a DataTemplate with the context of the row.  In this demo, the implementation is trivial, all I did was put a textblock, but you can do much more complex RowDetails on a real project.

    <DataTemplate x:Key="RowDetailsTemplate"> 
            <Grid TextBlock.Foreground="White"> 
                <Grid.RowDefinitions>
                    <RowDefinition /> 
                    <RowDefinition />                 
                </Grid.RowDefinitions>
                <TextBlock Text="RowDetails Go here"  Grid.Row="0"/>             
                <TextBlock Text="{Binding }" Grid.Row="1"/> 
            </Grid>
            
    </DataTemplate>

    The main reason to mention RowDetailsTemplate is to emphasize the ‘synchronization’ that needs to happen when a row is selected:  RowDetailsTemplate, RowBackground, and RowHeader’s background should  all align to make sure their backgrounds are color coordinated.   In this case, if you look at the templates above, I did make sure they matched for selection and set the background to the ‘dark blue’ gradient.


    Closing Thoughts:
    This writing is not all inclusive; there is lots more you can do to style the datagrid. 
    I do have to say, it is neat that in the usual “WPF designer friendly” mark-up tweaks, we went from a plain grid (see left) to a styled grid ( see right) with out writing a single line of code.  

    CheesyDataGridSummary

     

    What now?
    To compliment this styling tutorial, I recommend Colin Eberhardt’sWPF Datagrid Practical Examples” article. He does a great job at sharing insights into data binding, validating and even styling the datagrid. Thanks Colin!

     
    The source code for this writing is here.   Thanks for reading this

  • Jaime Rodriguez

    Binding.StringFormat only works on TargetType string

    • 0 Comments

    I am a fan of BindingBase.StringFormat (introduced in WPF 3.51sp1).
    To learn almost every thing you need to know about StringFormat, check Mike Hillberg’s post on StringFormat; he covers MultiBindings, ContentStringFormat, HeaderStringFormat, etc.. 

    This week is I wanted to do StringFormat on a CommandParameter  (type object).  I assumed Binding.StringFormat would do the trick but then I tried it (about 5 different ways) and it did not work.    

    Per Sam (data binding dev lead) this is a known limitation on 3.5 SP1: if you want to use StringFormat, the target type for your binding needs to be a string.     The workaround for other target types is to to write your own IValueConverter; this is very trivial and Kent Boogaart already has a nice generic Format Value Converter on his WPF converters codeplex project.

    [Apologies if post came out uninteresting; it took me a good 45 minutes to digest that StringFormat would be smart enough to care about TargetType, so I wanted to post it to save the next 5 people a little time]..  

  • Jaime Rodriguez

    XAML guidelines part 3

    • 12 Comments

    There were 3 goals to the XAML guidelines series:

    1. Show that there is not a single right answer (that is why we interviewed multiple people, multiple projects)
    2. Document common practices and previous experiences that worked.
    3. Inspire others to share their own opinions and practices.

    In order to accomplish parts 2 and 3, I have typed a few of my recommended best practices for any one starting new..    

    Since not every one will agree with my opinions so I am labeling this a draft, I would love for people to chime in with better suggestions and comments agreeing or disagreeing with the ones I listed.  Feel free to leave comments, or write your own blog post and link to it from here.  You can also drop me an email directly via contact page.  

    I am planning to leave this open for at least a week and then try to update the document to go beyond draft.

    XAML Guidelines Draft  HTML, PDF, XPS and DOCX.

    For any one who finds this does not cover every thing they were wondering, please do let me know what I missed. I have at least two more topics that are related that I want to tackle next, but I figure partitioning them works best so we can build on a foundation.

    Happy coding!

Page 4 of 9 (222 items) «23456»