Welcome to MSDN Blogs Sign in | Join | Help

Recently a posted a set of questions around Silverlight Control licensing.  I was really happy with the number of responses I got.  Thank you all for replying.

To give you an idea of what the responses were like:

  • 15/17 Control Vendors license their controls
    • 15/15 write their own LicenseProvider or roll their own system (no surprise here but we wanted to validate that the LicFileLicenseProvider was not being used)
    • 13/15 perform design time validation
    • 13/15 perform runtime validation
  • 10/17 indicated that not having licensing support in Silverlight would affect their level of investment in Silverlight controls.

Thanks again for the responses, the data really helps us to make better decisions.

 

 

For any of you building 3rd party controls for Silverlight - I really need your feedback!

We are looking at what the requirements should be licensing - and how important it is to you that we provide licensing support (i.e. LicenseProvider) for Silverlight controls.

1) Do you use the LicFileLicenseProvider or do you roll your own LicenseProvider?

2) Do you use both design time validation and runtime validation or just one?  If one, which one?

3) Would the lack of licensing support affect your investment in building Silverlight controls?

Please email me at "jnak" at microsoft and include your company name.

Thank you so much.

XAML specification published, added to Microsoft's open promise

Specs that are shared include the following:

·         Xaml Object Mapping Specification 2006

·         WPF Xaml Vocabulary Specification 2006

If you are looking to write a file format import/export tool, these will definetly be a great help to you.

Recently I saw a post on the forums asking about how to get subproperties to show up in the Property Browser for WPF projects.  This inspired me to blog about it as I'm sure other people are also running into this question.

What do I mean by sub-properties?  Consider the following screen shot of the Property Browser:

Notice how to the left of the ExpandablePersonObject property there is a square with a '-' in it?  That is the expanded state for sub-properties.  When collapsed, it will show up as a '+'.

The sub-properties are the Age, Name and ShirtColor that are properties on the ExpandablePersonObject type (shares the same name as the property).

So the question is: how do I create a property for a type that shows my sub-properties?

The short answer is that the property or the type of the property needs to have the ExpandableObjectConverter TypeConverter applied to it.  That said, in order to fully answer that question, I created a project that illustrates the various scenarios (see attached zip to this post). 

There are two interesting cases, the first is for DependencyObject derived types and the second is for System.Object derived types.

In the case of DependencyObjects, you pretty much get the behavior for free because Cider itself adds the ExpandableObjectConverter to DependencyObjects (note: Blend has the same behavior as Cider for all this stuff, we designed it all together).

So, if I have a type such as this:

    public class PersonDependencyObject : DependencyObject
    {
        public static readonly DependencyProperty AgeProperty = DependencyProperty.Register("Age", typeof(int), typeof(PersonDependencyObject));

        public int Age
        {
            get { return (int)GetValue(AgeProperty); }
            set { SetValue(AgeProperty, value); }
        }

(. . .)

and the property on the control that will be selected in the designer is:

         public PersonDependencyObject PersonDependencyObject;

The Age, ShirtColor and Name properties on the PersonDependencyObject type will be shown in the Property Browser.

If the type of the property is derived from object:

    public class PersonObject
    {
        private string _Name = "";
        private int _Age = 0;
        private Brush _ShirtColor = Brushes.Blue;

        public string Name
        {
            get { return _Name; }
            set { _Name = value; }
        }
(. . .)

You have a little more work to do.

You can either set the TypeConverter on the type itself:

    [TypeConverter(typeof(ExpandableObjectConverter))]
    public class ExpandablePersonObject (. . .)

or on the property on the control:

        [TypeConverter(typeof(ExpandableObjectConverter))]
        public PersonObject PersonObjectWithExpansion

If you do either of these, you will get the sub-properties showing up for that property.

You will notice one other thing here, in order for sub-properties to show up, you need to ensure that the property is editable in XAML.  That is, if you programmatically set an instance on the property or set an instance as the default property, you'll get the + to expand/collapse but the subproperties will not show up underneath. 

For example if I were to programmatically set my property to an instance:

         public PersonControl()
        {
            InitializeComponent();
            PersonDependencyObject = new PersonDependencyObject();
        }

Looking at the Property Browser:

Notice how you get the expander that shows the subproperties expanded but you cannot see or edit them.  This is because the property is not set in XAML.  We want to improve this experience in a future release however this is what we are stuck with for now.

For properties that do not have a value, if you click the dropdown and select the type in the drop down, that will create a new instance in the XAML  For example, if in my attached sample I select the "PersonObject" type in the drop down for the PersonObjectWithExpansion property, I will get the following added to the XAML:

        <local:PersonControl>
            <local:PersonControl.PersonObjectWithExpansion>
                <local:PersonObject Age="0" Name="" ShirtColor="Blue" />
            </local:PersonControl.PersonObjectWithExpansion>
        </local:PersonControl>

The sub-properties will be expanded and you can edit them using the property browser.

You might now ask if there is a way to customize that drop down of types...  the answer is yes!  There is.  For this you will have to use the Metadata Store to add the attribute and the attribute is the NewItemTypesAttribute.  When you decorate a property with the NewItemTypesAttribute, you specify the list of types that are compatible to be instantiated and set as the property value for the given property -- i.e. it shows up in the drop down.

Want to work on the designer and tools for WPF and Silverlight?  Here's your opportunity, and it's an amazing one.

We're really excited about all the cool work we have coming in the next Visual Studio release, code named Dev10 and the division is investing in Cider in order to ensure that we have the team to make it all happen.

Microsoft is a really unique and special place to work, if you are passionate about software, about next gen technologies and the developer experience, click on the links below.

Also look at our jobs page on WindowsClient.net

Check it out: https://downloads.channel8.msdn.com/

DreamSpark is simple, it's all about giving students Microsoft professional-level developer and design tools at no charge so you can chase your dreams and create the next big breakthrough in technology - or just get a head start on your career.

Following up on the great design time experience that they developed for their SandDock for WPF, divelements has just released their SandRibbon control that includes an impressive array of design time features.

The SandRibbon is a control suite that allows you to add an Office 2007 Ribbon UI to your application.

The good folks at divelements have made use of the following extensibility features:

  • Context Menu Actions
  • DefaultInitializer
  • DesignModeValueProvider
  • Adorners
  • Policy
  • PlacementAdapter
  • ParentAdapter

It's really great to see the power of Cider's extensibility in action.

One of the things we've been working on as a team is a guide to help Windows Forms developers ramp up on the WPF Designer in Visual Studio 2008.  Thanks to the great writing talents of Jim and the whole Cider PM team, this white paper is now available for all to enjoy.

http://msdn2.microsoft.com/en-us/library/cc165605.aspx

On 1/29/2008, Actipro released a new build of their WPF Studio.  You'll recall that I blogged about their use of extensibility to improve the design time interaction of their controls.  This new release ups the ante with drag and drop layout, a really cool image picker and a host of other improvements across their task panes.

Check out: http://www.actiprosoftware.com/Products/DotNet/WPF/Ribbon/DesignerSupport.aspx

Here's a shot of the image picker:

For a hint on how they did this, here is a tip from resident Cider Architect Brian Pepin:

There is a service called ExternalResourceService that is defined in Microsoft.Windows.Design.Markup.  It allows you to enumerate the images (and other resources) in the project.  When you find an image you want, it is returned as a type called BinaryResource.  BinaryResource can be used to obtain a stream and it can also be used to obtain a special kind of URI called a "stream" URI.  If you pass this URI to a WPF API that uses URIs, or if you pass it to WebRequest.Create, you can get back a stream as well. 

This is how we handle all resources in the designer and it allows you to ignore the details of the URI.

I also updated the screen shots on the previous post referenced above.

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.

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.

 

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!

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.

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/

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

More Posts Next page »
 
Page view tracker