• Cloudy in Seattle

    Mincom Case Study

    • 1 Comments

    Here is a case study of one of the companies we've been working with, Mincom. 

    http://www.microsoft.com/casestudies/casestudy.aspx?casestudyid=4000001266

    They've made great use of Visual Studio 2008 and specifically of Cider/WPF.

  • Cloudy in Seattle

    Showing Attached Properties in the Cider WPF Designer

    • 2 Comments

    If you create a type that defines an attached property, you will notice that this attached property does not show up in the WPF Designer (Cider) Property Browser.  So how do you get it to show up and what level of control do you have over when it shows up?

    As it turns out, you can use the following attributes to control how your properties show up in the Property Browser:

    AttachedPropertyBrowsableWhenAttributePresentAttribute
    AttachedPropertyBrowsableForChildrenAttribute
    AttachedPropertyBrowsableForTypeAttribute

    You apply them to the get accessor of your attached property definition, like this:

        public class WhenAttributePresentTestControl : Grid
        {
            public static readonly DependencyProperty ShowWhenCustomAttributePresentProperty = DependencyProperty.RegisterAttached(
              "ShowWhenCustomAttributePresent",
              typeof(int),
              typeof(WhenAttributePresentTestControl));

            public static void SetShowWhenCustomAttributePresent(UIElement element, int value)
            {
                element.SetValue(ShowWhenCustomAttributePresentProperty, value);
            }

            [AttachedPropertyBrowsableWhenAttributePresentAttribute(typeof(MyCustomAttribute))]
            public static int GetShowWhenCustomAttributePresent(UIElement element)
            {
                return (int)element.GetValue(ShowWhenCustomAttributePresentProperty);
            }
        }

    One thing to keep in mind is that one of the requirements of showing attached properties in the designer is that the owning type needs to have been loaded by the designer.  This happens whenever the designer accesses the type because it is in the XAML source or is a dependency of an element loaded from the XAML source.

    Attached to this post is an example of using all 3 of these attributes.

    AttachedPropertyBrowsableWhenAttributePresentAttribute

    This attribute allows you to specify that your attached property show up in the Property Browser when the selected item has a given attribute applied to it.  If the attribute has a default value, that value also has to be different from the default value.

    In the example above that passes in "MyCustomAttribute" as the attribute to look for, when CustomLabel below is selected in the designer, the Property Browser will show the ShowWhenCustomAttribute attached property however it will not when CustomLabelNoCustomAttribute is selected:

        [MyCustomAttribute]
        public class CustomLabel : Label
        {
        }

        public class CustomLabelNoCustomAttribute : Label
        {
        }

    AttachedPropertyBrowsableForChildrenAttribute

    This attribute indicates that the attached property should be available for the children of the given control.  There are two main flavors for this attribute.  One that includes descendants and one that does not. As you might expect including descendants refers to including all children or simply the direct children of the control.

            [AttachedPropertyBrowsableForChildrenAttribute(IncludeDescendants=true)]
            public static int GetShowForChildrenDeep(UIElement element)
            {
                return (int)element.GetValue(ShowForChildrenDeepProperty);
            }

    AttachedPropertyBrowsableForType

    This attribute allows you to specify that your attached property show up when a given type or types derived from that type are selected in the designer.  The following sample would make your attached property show up when any Grid, derived Grid, Button or derived Button is selected.

            [AttachedPropertyBrowsableForType(typeof(Grid))]
            [AttachedPropertyBrowsableForType(typeof(Button))]
            public static int GetShowForTypes(UIElement element)
            {
                return (int)element.GetValue(ShowForTypesProperty);
            }

    Sample Attached

    I have attached a sample to this blog post the shows the usage of all the attributes listed above in the Cider WPF Designer.

     

  • Cloudy in Seattle

    DevComponents DotNetBar Suite for WPF

    • 3 Comments

    DevComponents recently released their DotNetBar Suite for WPF and it is loaded with design time features.  Using Cider Extensibility, DevComponents really has put together one of the richest design times I've seen to date.

    Denis talks about the features on this blog post.

    The DotNetBar suite provides a set of controls that make it easy to build an application with an Office Ribbon, Window Management and an Outlook style Navigation Pane control. 

    The first thing to notice is that for the elements you care to move to other positions -- the buttons in the Ribbon (including on the application menu), and the windows in the application -- can be moved by simply clicking and dragging.  Very cool use of setting up a ParentAdapter correctly.

    Here's a sequence where I moved a button from the Recent Documents list to the Command Button area to the Application Menu main buttons to a location on the ribbon -- all using drag drop.

    For redocking the windows at design time, the user gets the Visual Studio-esque docking targets and highlighting:

    Much better than having to find the right set of XAML to modify right?

    Each selectable element also has a popup menu associated with it that allows the user to edit the controls in place.

    The application Menu:

    Drop down buttons (these can be dragged dropped around the whole UI to multiple drop targets):

    The Ribbon Tab:

     

    And Windows:

     

    DevComponents have made use of the following Cider Extensibility features to make this happen: Adorners, DefaultInitializers (to setup the XAML for their controls when they are created from the toolbox), and ParentAdapter (for drag/drop move/repositioning of theirr controls).

    Really is a great example of how powerful the Adorner Extensibility features are in Cider.

    Again -- I am looking for more design time examples to feature on this blog so please contact me with your examples!

  • Cloudy in Seattle

    Workaround for Style.Triggers Design Time Issue

    • 3 Comments

    I've received two bug reports from Control Vendors regarding Style.Triggers not working correctly at design time in the WPF Designer RTM.  Fortunately, we do have a workaround to the problem.  Suppose you have a trigger defined as follows:

         <Style TargetType="{x:Type local:CustomControl1}">
            <Style.Triggers>
                <Trigger Property="local:CustomControl1.SecondTemplate" Value="True">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type local:CustomControl1}">
                                <Border Background="Red"
                                BorderBrush="Green"
                                BorderThickness="4">
                                </Border>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Trigger>
            </Style.Triggers>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type local:CustomControl1}">
                        <Border Background="{TemplateBinding Background}"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}">
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

     What you would expect is that in the designer when you set the SecondTemplate property to true you would get something that looks like this:

    Unfortunately, the style doesn't update.

    To work around this issue, if you define triggers for both the true and false values, you will get the desired behavior:

       <Style TargetType="{x:Type local:CustomControl1}">
            <Style.Triggers>
                <Trigger Property="local:CustomControl1.SecondTemplate" Value="True">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type local:CustomControl1}">
                                <Border Background="Red"
                                BorderBrush="Green"
                                BorderThickness="4">
                                </Border>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Trigger>
                <Trigger Property="local:CustomControl1.SecondTemplate" Value="false">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type local:CustomControl1}">
                                <Border Background="{TemplateBinding Background}"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}">
                                </Border>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Trigger>
            </Style.Triggers>
        </Style>

    Hope that helps!

    This sample is attached.  When you open the sample it will be in a state where the style triggers don't, well, trigger at design time.  If you uncomment the workaround and comment the original style, you will see the style triggers will then work in the designer.

  • Cloudy in Seattle

    Pistachio - “WPF Resource Visualizer”

    • 1 Comments

    There are definitely some cool 3rd party WPF tools coming out as of late -- for example, Mole.  Here is another cool one that helps you to get a handle on your WPF resources.

    http://www.granthinkson.com/2007/11/08/announcing-pistachio-wpf-resource-visualizer/

  • Cloudy in Seattle

    Actipro Ribbon - Office 2007 UI

    • 3 Comments

    Another great example of cool design time functionality in Cider (WPF Designer in Visual Studio 2008) comes from Actipro.  Their Office Ribbon control uses Cider Extensibility to add task panes invoked by an adorner that makes configuring their control a breeze.

    For example, when the main Ribbon is selected a little widget adorner in the upper right hand corner is shown and when clicked will bring up a task pane that uses the Cider Editing Model to make updates to the XAML:

    Likewise, they've done that for TabGroup, Tab and StackPanel tasks:

    There are other examples as well, virtually every major clickable element has a task pane associated with it.  Very cool.

    You can also drag and drop elements of your Ribbon around -- which really makes designing your control really easy.

    Actipro has also made good use of the Property Browser, the collection editors have all been setup using the NewItemTypesAttribute which allows the end user of their controls to use the collection editors to configure the Ribbon:

    Similarly, with non collection properties in the Property Browser:

    Actipro uses the following Cider Extensibility points: DesignModeValueProvider (set a different value for the instance in the UI from that which is serialized to XAML), lots of Adorners, and Property Editing Extensibility.

    For additional information, see http://www.actiprosoftware.com/Products/DotNet/WPF/Ribbon/DesignerSupport.aspx

  • Cloudy in Seattle

    SandDock for WPF by Divelements

    • 4 Comments

    Now that Visual Studio 2008 has been released, one of the real fruits of my job is to see how our customers end up using our product.  Specifically, I really enjoy seeing how WPF Control Developers end up using the WPF Designer Extensibility API that I talk about so much on this blog.

    If you have examples of how you are using extensibility for your WPF controls -- please drop me a line (you can send a message from this blog) and I'll definitely blog about your product.

    The first example I received that shows off design time extensibility comes from divelements - SandDock for WPF.

    SanDock is a very cool set of controls that provide a vast array of Window Management functionality.  Here is a shot of their demo application inside the designer. (showing off how you can redock your windows at design time using adorners)

    Here they use MenuActions to add context menu items that help the user configure their application:

    Finally, here is a more clear shot of their clever use of adorners to provide a design time window docking functionality similar to the dockable windows feature in Visual Studio:

     

    They have also made their own EverythingPolicy (to show adorners on more elements than just the primary selection), ParentAdapter (to handle reparenting), and DefaultInitializer (note the XAML spit when instantiating their controls from the toolbox),

    Lots of great illustrations of how you can use the power of Cider's extensibility model to create a first class design time experience.

    Here is the divelements page describing the designer support: http://www.divelements.co.uk/net/controls/sanddockwpf/documentation/designer.htm

  • Cloudy in Seattle

    Giving Focus to Adorners

    • 3 Comments

    If you add a TextBox as an adorner to your design time, by default you will not be able to give that TextBox focus.  That is, you won't be able to set the cursor in it so that you can type.

    Similarly, if you use a TabControl as an adorner, by default you won't be able to switch the tabs by clicking on them.

    The solution is to set the AdornerPanel.IsContentFocusable property to true:

                AdornerPanel ap = new AdornerPanel();
                ap.IsContentFocusable = true;

    One caveat here: we know we have a bug in the TextBox keyboard handling where the delete key will always delete the selected control, even when the user is in text entry mode in a TextBox -- i.e. hitting the delete key won't delete the text, it will delete the control.

  • Cloudy in Seattle

    See Jackass 2.5 Free Courtesy of Blockbuster and experience Silverlight

    • 3 Comments

    Cider is currently known as the "WPF Designer for Visual Studio" but we're also in the works of being known as the "Silverlight Designer for Visual Studio". 

    In other words, we care about Silverlight and the following is pretty cool:

    ·         On December 19th, Blockbuster will premiere the first full-length feature film, Jackass 2.5, directly to online audiences on Windows and Mac using Microsoft Silverlight

    ·         Jackass 2.5 will be made available for free, for anyone in the US 17 or older, courtesy of Blockbuster at www.blockbuster.jackassworld.com beginning December 19th through December 31st, 2007

    ·         This is one of the largest projects in Blockbuster history, made possible using the rich media CDN from Limelight Networks and Silverlight

    ·         Silverlight is a 1.5MB cross-browser, cross-platform plugin for IE, Firefox and Safari users.  Details and download at http://www.microsoft.com/silverlight

    The ecosystem around Silverlight is continuing to grow, with an impressive line-up of customers like MLB.com, BMW, Sony Ericsson, Baidu (#1 search site in PRC), NBA.com, Entertainment Tonight (CBS/Paramount) and UVNTV.com, to name a few.  See more at http://silverlight.net/Showcase/

  • Cloudy in Seattle

    Specifying a Toolbox Icon for a Control in the WPF Designer

    • 2 Comments

    Recently I had a customer point out the following from the documentation: 

    Differences in Specifying Toolbox icons

    In the Windows Forms Designer framework, you specify a Toolbox icon for your custom control by applying the ToolboxBitmapAttribute to your control class.

    In the WPF Designer framework, you use an embedded resource and a naming convention to specify a Toolbox bitmap. In addition, you use the ToolboxBrowsableAttribute to restrict which types in an assembly are available for populating a Toolbox.

    Followed by the question "What is the naming convention?"

    I thought I'd answer that question by posting to my blog as it is not the first time I've had that question. 

    First, a note about the ToolboxBrowsableAttribute, it is defined in Microsoft.Windows.Design.dll so you don't want to use it declaratively in your code because that would require making a reference to Microsoft.Windows.Design.dll which will only be available on machines that have Visual Studio 2008 installed.  Use the Metadata Store as discussed here and Metadata Assemblies as discussed here.

    Toolbox Icon Naming Convention 

    1. To add an image representing your control to a type, simply add an image at the same hierarchy and name in the project, and mark that image as an EmbeddedResource:

    1. Cider will search for resources whose file name without extension matches the type name of the control, including the namespace with a “.icon[*].{BMP| PNG | GIF | JPG | JPEG}” . 
      1. Note that folders in your project affect the namespace in which embedded resources are found.
      2. Supported extensions and file types are: BMP, GIF, JPG, JPEG and PNG
      3. Recommended image size for Bitmap based file formats is 64x64.
      4. The .icon[*] in the naming convention is optional and allows you to specify multiple sizes of the image that is used as the icon.  The match follows the following algorithm:
        1. If there is an exact match on size (both dimensions) use it
        2. Use the closest match based on size and aspect ratio
      5. If a given resource file is not a valid image file, the next match will be used until one is found
    2. Different hosts (i.e. Cider or Sparkle) use different image sizes for their toolbox icon. 
      1. Sparkle uses 24x24 for their large size and 12x12 for their small size
      2. Cider (WPF Designer in Visual Studio) uses 16x16
    3. This design will also be used to find a default icon for types added to the Collection Editor or Sub-Properties Editor “new instance” functionality. 

    Example

     

    Type is defined as:

     

    namespace Proseware.Core.Controls

    {

        public partial class ProseControl : UserControl

        {

            public ProseControl()

            {

                InitializeComponent();

            }

        }

    }

     

    Default namespace: Proseware.Core.Controls

     

    ProseControl.Icon.png is added as an Embedded Resource. 

     

     

    This causes the image at Proseware.Core.Controls.ProseControl.Icon.png from the resources inside the assembly in which ProseControl is contained to be used as the toolbox icon:

     

    (view from reflector)

     

     

    Multiple Sizes 

     

    The naming convention supports multiple image sizes.  For the following example:

     

    Type is defined as:

     

    namespace Proseware.Core.Controls

    {

        public partial class ProseControl : UserControl

        {

            public ProseControl()

            {

                InitializeComponent();

            }

        }

    }

     

    Default namespace: Proseware.Core.Controls

     

    For the ProseControl type, the following images in the resources will all be found and the best match for size will be used. 

    Proseware.Core.Controls.ProseControl.Icon.Large.png

    Proseware.Core.Controls.ProseControl.Icon.Medium.png

    Proseware.Core.Controls.ProseControl.Icon.ReallyLarge.png

     

    Or, alternatively (the ‘.’ After Icon is not required but is acceptable):

     

    Proseware.Core.Controls.ProseControl.IconLarge.png

    Proseware.Core.Controls.ProseControl.IconMedium.png

    Proseware.Core.Controls.ProseControl.IconReallyLarge.png

     

    If the desired size by the host is 64 pixels by 64 pixels, and Proseware.Core.Controls.ProseControl.Icon.Large.png is the best match based on size and aspect ratio, it will be used.  All of the images will be looked at.

     

    If there are 2 images with the same size and aspect ratio, the host will decide which it will use.

     

    Sample Project

    Attached to this post is a sample project that illustrates how to get an icon defined for your control.  To test, build the solution, right click on the toolbox and click "Choose Items...".  Switch to the WPF Components tab and navigate to one of the control assemblies.  You will then see your control with it's icon on the toolbox.

  • Cloudy in Seattle

    Mole 2.1 - WPF Runtime Inspection Tool

    • 3 Comments

     Ran across this today and I thought I would pass it along as it is a very useful tool for WPF developers.

    Mole II is a high performance, full featured Visual Studio Visualizer which allows you to inspect elements in the WPF visual tree or logical tree, as well as all properties of those elements.

    http://karlshifflett.wordpress.com/mole-visual-studio-visualizer-for-wpf/

  • Cloudy in Seattle

    How to get the best out of the WPF designer when laying out your WPF app

    • 2 Comments

    Mark Wilson-Thomas is our resident WPF Layout expert and is leveraging my blog to get some great information out about how the VS 2008 WPF Designer approaches layout:

    How to get the best out of the WPF designer when laying out your WPF app

    Lots of folks have asked what the reasoning is for the WPF designer giving a new control instance on the design surface a width and height, and margins so that it stays where you drop it and sizes to a reasonable default size. The story of “why we emit margins to make things feel like anchored controls in Windows Forms” by default in the Cider layout system is really about making it possible to traverse two paths to your final layout, and to cross over from one to the other:

    Path 1: This is the popular “Visual Place-and-size” path that people have been used to on practically every GUI designer that's shipped since Visual Basic.

    Path 2: This is the “Container first” path, where you lay out the Grid(s) or other containers that will govern the layout, then place controls inside them (generally with zero margin) and let the container take care of the resize behavior for you

    Path 2 is an approach I’ve seen advocated in several posts and discussions on the topic. Both from a “WPF platform-purist” point of view and an experienced Web UI developers point of view, I agree this a clear and straightforward way of thinking about layout in WPF. However if you’re one of the many millions of developers who have been working with Windows Forms, VB, etc for years, and have never built a web app, it will probably not be an easy transition for you to be forced to start thinking this way for your first app building experiences – and in addition, you may never want to build a fully resizable app.

    So if you’re a developer with that set of experience, what we let you do is get a pretty much functional WPF app in the traditional way you always have using path 1 (and actually for a lot of applications you might even stop there). If you wish to, we then give you help to start dropping gridlines into your design and snapping them to your controls/your controls to them (getting the zero margins you are looking for) ready to move into Auto-layout-land. Unfortunately, we didn’t have time on Cider v1  to deliver the full set of features that would give you the “flip-to-auto” part of the story on the design surface, so you have to go to XAML or the property inspector to make it happen, and when you do the behavior of the design surface can become a little “quirky” in places.

    So, what’s the best path for getting great layout in the designer then?

    The application layout path that works best right now if you want to use the WPF design surface is:

    1. Place your controls and get them roughly where you want them in your outermost grid
    2. Drop in your gridlines to control resize behavior but don’t start switching your grid rows/columns and controls into Auto sizing yet
    3. Snap your controls to the gridlines to zero out margins where that’s what you want (or multi-select your controls in the property inspector and zero margins on the whole set of selected controls’ margins)
    4. When everything’s done, flip your controls and grid rows/columns as appropriate into auto-sizing using XAML or the PI.

    NOTE 1: If you need to move/resize things after this step, it’s best to flip back out of auto first.
    NOTE 2: Steps 1 & 2 are pretty much interchangeable

    Why doesn’t the designer favor auto layouts by default?

    I think it's reasonable to argue we should have started with a mode that favored auto layouts by placing new controls with no margins in whatever container they were added to (rather than the method we have used) by default. However after many discussions in the team we felt this kind of total break with the past for our default experience would be just too jarring for too many existing UI technology users. 

    I do think that a designer setting that allowed you to have a more "start with auto" approach would be a useful feature, and we'll think about that for future releases. As an aside, right now one way to work in a "start with auto" approach should you wish to do so, is to work entirely in the XAML editor and not use the toolbox for control creation at all. That way you will get only the properties you explicitly wanted at creation time.

  • Cloudy in Seattle

    Visual Studio 2008 RTM Crashing when Creating a WPF Project?

    • 0 Comments

    We've been seeing some issues where VS 2008 crashes when creating a new WPF project.  The underlying issue is that on certain machine configurations, the .Net Framework is not updating correctly.

    In order to short circuit diagnosing that you're in this state, one of my colleagues on the deployment team has written a tool that will tell you whether or not the .Net Framework is installed correctly or not.

    If you are having issues, please take a look at this tool http://blogs.msdn.com/aaronru/archive/2007/11/29/net-framework-3-5-installation-validation-tool.aspx.  It will tell you whether or not your .Net Framework installation is correctly installed.

    After that, have a look at this tool to collect log files: http://blogs.msdn.com/astebner/archive/2007/08/01/4172276.aspx

    If you do have this issue, please contact the Cider team directly via our forum at: http://forums.microsoft.com/MSDN/ShowForum.aspx?ForumID=169&SiteID=1 or via my blog and have the results of the .Net Framework install check and log files ready. 

    Thank you and sorry for any inconveniences.

  • Cloudy in Seattle

    Visual Studio 2008 has shipped!

    • 0 Comments

    This is a pretty exciting day as Visual Studio 2008 has shipped.  This is the first product I've shipped with Microsoft which makes it a milestone for me.  I think back to what feels like yesterday (2 years ago) when I started on Project Cider and all we had was a half working XAML previewer. 

    Since I represented my team in the Developer Division shiproom, late last week I got to sign these big 6 foot Visual Studio boxes and received a t-shirt of all of the best shiproom quotes.  I was happy to see I got quoted twice!

    • "We have no crud in our database" (referring to our bug database)
    • "This bug is best illustrated by watching the video" (I created a video of a bug repro to support my arguments to get an approval to check in a fix for that bug)

     It really has been a great experience for me and I've learned a lot over the past two years.  I really look forward to working on our next release.

     Here is Soma's announcement:

  • Cloudy in Seattle

    Don't do that in the WPF Designer (Cider)!

    • 3 Comments

    One of the challenges of building a designer after the framework has shipped (as is the case with Cider) is that the designer isn't always able to support all of the coding patterns that develop before the tools become available.

    This is not a new problem.  Brian Pepin wrote a similar article to this one back in 2004 about Windows Forms.

    This post will discuss some of those patterns that are valid at runtime but are not supported by Cider.

    Code Behind in Controls

    Cider, like Blend is fundamentally a XAML designer.  We load up XAML files.  When you write code behind for a particular control, that code behind may or may not be run at design time.

    If the code behind is in the constructor of a control that is hosted by a parent in the Cider designer, it will be run when that control is loaded onto the design surface.  For instance, if I create a UserControl named MyUserControl and place it on a Window, the constructor for MyUserControl will be run when that Window is loaded in Cider.

    However, if I am designing MyUserControl in Cider, because that type is being modified and created at that time, we don't instantiate MyUserControl -- which in turn means that none of the code behind for MyUserControl will be run.

    By the same logic, the code behind for any Window that is being designed will also never be run.

    Additionally, if you ever load XAML that binds to custom properties for a type being designed (i.e. Window is being designed or MyUserControl is being designed), those bindings will fail because again, the instance that is on the designer is the base class (Window, UserControl) of the type you are designing and not the actual type.

    For example:

    <Window x:Class="DontDoThis.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="300" Width="300" Name="MainWindow">
        <Grid>
            <!--Notice how I can't bind to a Custom property on Window1 since the CustomInt property doesn't exist at design time-->
            <TextBox Text="{Binding ElementName=MainWindow, Path=CustomInt}" Height="29" Margin="55,28,77,0" VerticalAlignment="Top" />
        </Grid>
    </Window>

    Base Classes

    As I've alluded to above, when we design a type, we instantiate its base class and show that in the designer.  What that means is that the base class for any type that you wish to show in the designer must be concrete (i.e. not abstract) and also have a public default constructor.

    That is, if I derive a class AbstractDerivedWindow from Window and then derive ConcreteDerivedWindow from AbstractDerivedWindow and try to load up and design ConcreteDerivedWindow, we will fail since we try to instantiate AbstractDerivedWindow, which we cannot.

    More concretely:

    <loc:AbstractDerivedWindow x:Class="DontDoThis.ConcreteDerivedWindow" . . . > . . . </loc:AbstractDerivedWindow>

    will not load in the designer with the error: Type 'AbstractDerivedWindow' is not usable as an object element because it is not public or does not define a public parameterless constructor or a type converter.

    Setting Property Values in Code Behind 

    For compiled controls, for example a UserControl on a Window, that control is instantiated XAML + code which means that the code behind will run for that UserControl when it is on the design surface.

    If the code behind for that UserControl makes property changes, our model will not pick that up... which will result in the model and the designer getting out of sync with each other.

    In some situations, that isn't so bad, consider the following:

        public partial class UserControl2 : UserControl
        {
            public UserControl2()
            {
                InitializeComponent();
                Background = Brushes.Blue;
            }

    Cider will look at the properties that are set on a control after it's constructor has run and treat those values as the default values regardless of whether or not they are truly the default value as per the Dependency Property definition, set by the XAML for that control (i.e. UserControl2.xaml) or set programmatically as above.

    When I instantiate UserControl2 above on Window1.xaml, the Background property is set to Blue.  If I set the Background property locally:

    <loc:UserControl2 Background="Cyan" /> 

    It changes as expected and when I delete the Background attribute in the XAML (<loc:UserControl2/>) the Background goes back to Blue.

    That said, there are situations like the following where our designer will not match the runtime values because the properties are being set programmatically and our model doesn't pick it up.

        public class CustomControl1 : Button
        {
            String property_One;

            public String Property_One
            {
                get
                {
                    return property_One;
                }
                set
                {
                    SolidColorBrush backgroundSolidColorBrush = System.Windows.Media.Brushes.Firebrick;
                    SolidColorBrush foregroundSolidColorBrush = System.Windows.Media.Brushes.White;
                    Background = backgroundSolidColorBrush;
                    Foreground = foregroundSolidColorBrush;
                    property_One = value;
                }
            }
        }

    And this control is instanced on a Window as follows:

    <custom:CustomControl1 Margin="11,36,11,124" Property_One="One"/>

    In this case, due to some internal "shadow property/design mode value provider" magic we do in the designer, the Background and Foreground properties are set to Firebrick and White respectively at runtime but not in the designer.

    It's also important to note that the designer does not make calls to property accessor methods (get/set) for Dependency Properties.

    Finally

    Along the same lines as what I discuss here and some of my other "why doesn't my XAML load" posts, Jim Galysn has written a great post about troubleshooting designer load failures.

  • Cloudy in Seattle

    Bug in Finding Metadata Assemblies

    • 1 Comments

    As it turns out, we have a bug in finding metadata assemblies that will be in Visual Studio 2008 RTM.  I described how we find and load metadata assemblies in a previous post and the bug pertains to the situation where:

    • The main assembly is being loaded from the GAC
    • The project where the main assembly is being loaded is not referenced by the project
    • You have your main and metadata assemblies in a folder defined in the AssemblyFolders in the registry

    The main line scenarios where this will be true is:

    • Loading metadata while populating the items in the Choose Toolbox Items (i.e. for ToolboxBrowsableAttribute)
    • Instantiating a control from the toolbox the first time in a project (the reference isn't made yet)

    Workaround

    In order to handle all of the situations (note that your customers may GAC your assemblies on you provided your assemblies are strong named) you need to provide 2 sets of design time assemblies (in your AssemblyFolder): 

    • MyAssembly.Design.dll and/or MyAssembly.VisualStudio.Design.dll
    • MyAssembly.dll.Design.dll and/or MyAssembly.dll.VisualStudio.Design.dll

    Sorry for the inconvenience, at least there is a reasonable workaround.

  • Cloudy in Seattle

    How to get my XAML to show up in the WPF Designer: IMultiValueConverter

    • 1 Comments

    Recently I made a post about how to deal with Application.Current at design time.  I thought I'd follow that up with another example of why your XAML may not show up in the WPF Designer (Cider) due to assumptions that are not true at design time.

    In this case, we're talking about implementing an IMultiValueConverter for a MultiBinding:

        public class SampleConverter : IMultiValueConverter
        {
            public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                string text = (string)values[0];
                Brush backgroundBrush = (Brush) values[1];
                return text + backgroundBrush.ToString();
            }
            (. . .)
        }

    In my sample, I am using this SampleConverter in a ControlTemplate that is defined in Application.Resources:

            <ControlTemplate x:Key="ReadOnlyTextBlockTemplate" TargetType="{x:Type TextBox}">
                <ControlTemplate.Resources>
                    <loc:SampleConverter x:Key="SampleConverter"/>
                </ControlTemplate.Resources>
                <Border BorderBrush="Black" BorderThickness="1">
                    <TextBlock>
                        <TextBlock.Text>
                            <MultiBinding Converter="{StaticResource SampleConverter}">
                            <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Text"/>
                            <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Background"/>
                            </MultiBinding>
                        </TextBlock.Text>
                    </TextBlock>
                </Border>
            </ControlTemplate>

    This all works fine at runtime but at design time, I fail to load with the error:

    Error 1 Unable to cast object of type 'MS.Internal.NamedObject' to type 'System.String'. C:\Users\jnak.REDMOND\Desktop\MultiBindingExample\MultiBindingExample\App.xaml 13 21 MultiBindingExample

    If you attach another instance of Visual Studio and debug into this, you'll find this:

    Ahh, I made an assumption that is always true at runtime but is not always true at design time.

    There are situations like this where some of our hookup is still being worked out and your code needs to handle this in order to work correctly in the designer.

    The simple fix here is to deal with this exception being thrown or check the type before trying to cast it (or use a construct such as "as" and check for null).

    -- Project is attached for full repro.

  • Cloudy in Seattle

    Problems with Nested ItemsControls

    • 1 Comments

    As we approach the end of the Orcas project schedule (Visual Studio 2008) I've been doing some app building in order to help validate the quality of the product that we are shipping. 

    In doing so, I ran into a WPF bug that actually ended up costing me a fair amount of time. 

    I was trying to display a collection of teams where each team had a collection of tasks.  I used an ItemsControl to display the teams and inside the ItemTemplate for each team, I had an ItemsControl that displayed the tasks.

    I got the teams showing up but only the first task for the first team showed up.  I went on trying to debug this, using TextBlock set to various binding expressions so that I could see the data as DataBinding would see the data.  After a few hours of finding nothing wrong with my code, I hit the web and found that I had hit on a bug. 

    In fact, I found 2 bugs in this area:

    https://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2202842&SiteID=1

    http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1275132&SiteID=1

    There is an illustrative code sample in the forum posting so I didn't bother adding my own in this post.  I did want to raise awareness to this issue as there is a workaround (reference the DataTemplate for the ItemTemplate from resources) and I hope I can save someone some time.

  • Cloudy in Seattle

    Change in Behavior of AdornerProvider Activate and Deactivate Methods

    • 1 Comments

    We made a change post Visual Studio 2008 (Orcas) Beta 2 in the way the AdornerProvider.Activate() and AdornerProvider.Deactivate() methods are called. 

    In the past you could assume that the Activate() and Deactivate() methods would be called exactly once per AdornerProvider instance. 

    This is no longer true, in Visual Studio 2008 RTM, it will be possible that for a given AdornerProvider instance, the Activate() and Deactivate() methods will be called multiple times.  I had to update my TechEd samples to accomodate this.

  • Cloudy in Seattle

    .Net Framework Library Source Code

    • 2 Comments

    Scott Guthrie, a GM in the division I work in (Developer Division) has just made a great post about how Microsoft will be releasing the source code of the .Net Framework libraries along with Visual Studio 2008

    I know, I know, the majority of you that develop using one of the .Net techologies use reflector, so this may not seem like a big deal but consider the demo that Scott walks through that shows the integration of debugging, source and symbols.  This is such a win for .Net developers.

  • Cloudy in Seattle

    Have you seen the Toolbox Controls Installer?

    • 5 Comments

    A really cool new feature for Visual Studio 2008 is the Toolbox Controls Installer which as the name implies, allows you to add controls to the toolbox.  It's much easier than some of the previous VS package type work you used to need to do.

    There is a great sample in the Visual Studio SDK 2008 that shows you how to add a Windows Forms control, Web Control and WPF control to the toolbox programmatically.  The sample is called "Controls" -- and includes a WPF control and design time that may be familiar to those of you who have been reading my blog. (I'm surprised at how much mileage some of my samples get!)

    There is one caveat, in some of the online documentation that doesn't show the WPF example (it was added later), there is a missing registry value that is required to make this work:

                <Registry Root="HKLM" Key="$(var.VisualStudioRegistryRoot)\ToolboxControlsInstaller\CustomControlLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1631b3e7a8fbcce5" Value="Litware Controls" Type="string">
                  <Registry Name="Codebase" Value="[#CustomControlLibrary.dll]" Type="string" />
                  <Registry Name="WPFControls" Value="1" Type="string" />
                </Registry>

    The "WPFControls" value above.

    Very cool feature, really simplifies toolbox installation.  Note: this is implemented in VS 2008 Beta 2.

  • Cloudy in Seattle

    Dealing with Application.Current in Design Mode

    • 3 Comments

    There are a ton of WPF samples on MSDN which are really useful if you are developing in or learning WPF.  If you aren't aware of these samples, please check them out.

    One of the samples illustrates a point I want to make in my post today -- which is that as much as we try to avoid making you do this, sometimes you have to tweak your XAML/code in order to make it work within the Cider designer.

    The sample I am going to use is from a DataTemplate Sample located here:  http://msdn2.microsoft.com/en-us/library/aa972119.aspx

    If you load up this sample in VS 2008 beta 2 or later and (after conversion) you'll see that you can build and run the application no problem.  However, if you open up Window1.xaml, you'll notice that it fails to load in the designer and you'll get an error:

     'myTaskTemplate' resource not found.
       at MS.Internal.Helper.FindResourceHelper.DoTryCatchWhen(Object arg)
       at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Boolean isSingleParameter)
       at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler) 

    The problem occurs when we try to instantiate the TaskListDataTemplateSelector which is in the Window.Resources:

        <local:TaskListDataTemplateSelector x:Key="myDataTemplateSelector"/>

    This class does the following:

        public class TaskListDataTemplateSelector : DataTemplateSelector
        {
            public override DataTemplate
                SelectTemplate(object item, DependencyObject container)
            {
                if (item != null && item is Task)
                {
                    Task taskitem = item as Task;
                    Window window = Application.Current.MainWindow;

                    if (taskitem.Priority == 1)
                        return
                            window.FindResource("importantTaskTemplate") as DataTemplate;
                    else
                        return
                            window.FindResource("myTaskTemplate") as DataTemplate;
                }

                return null;
            }
        }

    Do you see the problem? What do you suppose Application.Current.MainWindow is in the designer?

    Since Visual Studio isn't a WPF application, for a long time during the development of Cider Application.Current returned null.  It no longer returns null but it is setup by Cider and has to do with Cider and not what you will get when you run your application. 

    In other words, calls to window.FindResource() will fail.

    So what can you do to make this work in the designer?  Well you have a few options, but if you've been following this blog for a long time you'll remember this post on detecting design mode.

    Since this situation nicely demonstrates the use of design mode, I'll solve the problem that way by changing the above code to check for Design Mode before accessing Application.Current.

            public override DataTemplate
                SelectTemplate(object item, DependencyObject container)
            {
                if (!DesignerProperties.GetIsInDesignMode(container) && item != null && item is Task)
                {
                    Task taskitem = item as Task;
                    Window window = Application.Current.MainWindow;

               (. . .)
            }

    The parameter you pass to GetIsInDesignMode doesn't really matter here since I'm counting on the default value which has been overriden to true in the context of a designer, the DependencyObject passed in will look for the IsInDesignMode attached property up it's tree.

    Now -- lo and behold!  The designer loads in Cider.

  • Cloudy in Seattle

    Using a Design Time Adorner to Setup Bindings Between Controls

    • 3 Comments

    [One warning -- the code to set the binding via the Editing Object Model will not work in VS 2008 beta 2 but will work in RTM] 

    Recently I wrote a post about writing Design Time Adorners. I had a good question come up on our Cider forum and I thought I would answer that question in the form of a post and sample which will illustrate how to accomplish much of what the person who made the post was trying to do.

    The question was essentially: How can I use design time adorners to make it easy to setup bindings between controls?

    I've updated my sample from my post on writing Design Time Adorners to not only set the Background of my SimpleCustomControl but also to set the Background of all of the siblings of my control to bind to the Background of my control -- as long as my SimpleCustomControl has a name and the Background property of the sibling control is not set.

    I piggy backed on the adorner that is already there so this post is really about using the Editing Object Model than adorners per se as the Editing Object Model is used in many situations, not just with adorners.

    How the design time works

    1) I start with my SimpleCustomControl in a Grid with 3 Buttons and 1 label as siblings.  Notice that one of the Buttons has it's Background set.

    2) I click on the Adorner for the SimpleCustomControl (the paint can that appears when the SimpleCustomControl is selected) and select a color.

    3) Notice how the Background for the siblings that didn't have the Background property set is now set to a binding to the Background of my SimpleCustomControl.

    So how did I get this to work?

    Implementation

    As mentioned above, I added all of the functionality to the existing handler for when the adorner gets clicked -- inside of _ColorsListControl_ClosePopup():

    void _ColorsListControl_ClosePopup(object sender, RoutedEventArgs e)
    {
         (. . .)
    }

    The first step is to get at the ModelItems for the siblings of the SimpleCustomControl.  I get at them by going to the parent of the SimpleCustomControl (the Grid) and then asking for all of the Grids children. 

                ModelItem parentModelItem = adornedElementModelItem.Parent;
                ModelProperty siblingsProperty = parentModelItem.Properties["Children"];
                ModelItemCollection siblings = siblingsProperty.Collection;

    The next step is to enumerate through those ModelItems and if the Background property is not set, set it to a binding:

                    foreach (ModelItem mi in siblings)
                    {
                        if (mi != adornedElementModelItem && !mi.Properties[Control.BackgroundProperty].IsSet)
                        {
                                (. . .) // set to a Binding
                        }
                    }

    Setting the Background to a Binding is done by creating a Binding instance, and setting the Background property of the sibling to it.  Then we setup the Binding by setting both the ElementName and Path properties.

                            using (var scope = mi.BeginEdit())
                            {
                                ModelItem binding = ModelFactory.CreateItem(Context, typeof(Binding));
                                mi.Properties[Control.BackgroundProperty].SetValue(binding);
                                binding.Properties["ElementName"].SetValue(adornedElementModelItem.Properties["Name"].Value);
                                binding.Properties["Path"].SetValue(new PropertyPath("Background"));

                                scope.Complete();
                            }

    And that's it -- one caveat is that as all my posts, this is quick and dirty code to illustrate a concept and this code may have to be tweaked to handle all of the various situations that can arise in the usage of the SimpleCustomControl.

    The code for this sample is attached to this blog post.

  • Cloudy in Seattle

    Design Time Adorners

    • 2 Comments

    I've posted about design time adorners a few times in the past however there have been some API changes since then so I thought I'd do a fresh post.

    What are design time adorners?

    Adorners are WPF elements that you can put on the Cider design surface when your custom control is instantiated and selected.  The end user who is using Cider can interact with your adorners to make updates to the XAML.

    For example, the selection handles, grid lines and rails when a Grid is selected are put on the design surface through the same adorner infrastructure I am describing in this post.

    Create an AdornerProvider

    The first step is to create an AdornerProvider that will add your adorners when your control is selected.  You will associate this AdornerProvider to your control using the Metadata Store as described in this post and this post.

    public class MyCustomAdornerProvider : PrimarySelectionAdornerProvider {
    Public MyCustomAdornerProvider () {
        Button buttonAdorner = new Button();
        buttonAdorner.Background = Brushes.Red;
        AdornerPanel panel = new AdornerPanel();
        panel.Children.Add(buttonAdorner);
        Adorners.Add(panel);
    } (...) }

    The key things to point out here are:

    • MyCustomAdornerProvider derives from PrimarySelectionAdornderProvider.  This means the adorners will light up when the control MyCustomAdornerProvder is applied to is selected.
    • Adorners are added to the surface by adding them to the Adorners property from the base class
    • An AdornerPanel is provides a lot of size/positioning help.  You don't strictly need it, an adorner added directly to the Adorners collection will show up in the upper left hand corner of the control it is associated with. 

    Add UIElements (the Adorners) to an AdornerPanel

    Setup the AdornerPlacementCollection with Position and Size Methods that are additive (take a factor + offset):

    • PositionRelativeToAdorner[Height/Width]
    • PositionRelationToContent[Height/Width]
    • SizeRelativeToAdornerDesired[Height/Width]
    • SizeRelativeToContent[Height/Width]

    In this API, "Content" refers to the control being adorned as its layed out on the design surface at 1X zoom.

    For example, to setup a button that will be above and to the left of the associated control when it is selected, you would do the following: 

    AdornerPlacementCollection placement = new AdornerPlacementCollection();
    placement.SizeRelativeToAdornerDesiredHeight(1.0, 0);
    placement.SizeRelativeToAdornerDesiredWidth(1.0, 0);
    placement.PositionRelativeToAdornerHeight(-1, -NudgeAmount);
    placement.PositionRelativeToAdornerWidth(-1, -NudgeAmount);
    AdornerPanel.SetPlacements(adorner, placement);

    To control how your adorners will act when zooming in and out, you can set the stretch properties on the AdornerPanel:

    AdornerPanel.Set[Vertical/Horizontal]Stretch

    Handle the interaction with your Adorners (handle events or setup tasks)

    For a lot of adorners that you will put on the design surface, handling the interaction is as simple as handling the events on the adorner itself.  For example:

    BouncyButton adorner = new BouncyButton();
    adorner.Click += new RoutedEventHandler(OnButtonClick);

    And in OnButtonClick() you can make changes to the XAML by working through the Editing Object Model.  The following sample code shows how to get the ModelItem for a given adorner and modify one of its properties through the ModelProperty class.

    ModelItem adornedElementModelItem = AdornerProperties.GetModel(_ColorsListControl);
    adornedElementModelItem.Properties[Control.BackgroundProperty].SetValue(new SolidColorBrush(_ColorsListControl.SelectedColor));

    Hook up your AdornerProvider to the control via the FeatureAttribute and MetadataStore

    The other thing you can do is use Tasks.  A Task associates a collection of input gestures that are bound to commands and the handlers for those commands.  Cider defines a set of ToolGestures that you can use as input gestures and thus handle -- in other words you can handle a click gesture on a Rectangle even though the Rectangle doesn't have a Click event.

    Task clickTask = new Task();
    clickTask.ToolCommandBindings.Add(new ToolCommandBinding(_ClickCommand, OnRectangleClick));
    clickTask.InputBindings.Add(new InputBinding(_ClickCommand, new ToolGesture(ToolAction.Click)));
    AdornerPanel.SetTask(adorner, clickTask);

    And as before, in OnRectangleClick() you can use the Editing Model (ModelItem, ModelProperty) to update the XAML from your adorner.

    Setup the Metadata

    Finally, in your Metadata Assembly, you will set up the metadata to associate your AdornerProvider to the control you want it to show up for:

    builder.AddCustomAttributes(typeof(ButtonWithDesignTime), new FeatureAttribute(typeof(PopupButtonAdornerProvider)));

    Finally

    I've attached a sample to this blog post that shows all of the concepts above and will work on beta 2 and RTM.

  • Cloudy in Seattle

    Cider Extensibility Help Documentation

    • 2 Comments

    One of our User Education writers who takes care of much of the Cider Extensibility documentation that will go into MSDN helped make the very early and beta set of docs on these subjects available for all to read. 

    You'll find them attached to this blog post.

    You'll also find that aside from this blog and Brian and Soak's blog, there is very little little information out there on how to write things such as property editors, design time adorners, MenuActions (adding context menu items to the right click menu) etc. etc..  which makes these docs really helpful at this point in time.

    Enjoy.

Page 6 of 9 (202 items) «45678»