Rob Relyea

xaml:Blog

February 2006 - Posts

  • Tim's tips for learning WPF

    Filed under:

    Tim Sneath posts a good set of resources to start your journey with WPF.

    He references my PDC 2005 Lap around WPF talk.  I wonder how that talk would change with more mature tools now?
    I'm beginning to post information for each of my talks (including my demo script, etc...).  If you are interested, check it out.

    My PDC 2003 talk was better rated by attendees than this talk...

    PostTypeIcon
    6,660 Views
  • Article about WPF Commands

    Filed under:

    Jelle Druyts wrote a nice article about WPF Commands that recently was posted here.

    Give him any feedback here.

     

    Would be interested in Nick Kramer's feedback on the article...he is the PM for WPF commanding...

    Update: Mike Taulty comments here. (adding a link to a writeup IanG did last year)

    PostTypeIcon
    10,905 Views
  • Wpf Xaml Namespace Update Tool for Feb2006 CTP

    Filed under: ,

    When we ship the Feb 2006 CTP, there are a few changes that will need to be done to all xaml files.

    We've created a tool to help upgrade your WPF XAML files to the Feb CTP.  It doesn't do an exhaustive upgrade, but it does handle the following major changes:

    • Change all xmlns uris of http://schemas.microsoft.com/winfx/avalon/2005 to http://schemas.microsoft.com/winfx/2006/xaml/presentation
    • Change all xmlns uris of http://schemas.microsoft.com/winfx/xaml/2005 to http://schemas.microsoft.com/winfx/2006/xaml
    • Replaces all mapping PIs with the new clr-namespace uri syntax:
      • Old Syntax 1
        • <?Mapping ClrNamespace="MyNS" XmlNamespace="other" Assembly="MyAssembly" ?>
        • <Page ... xmlns:foo="other">
      • Replacement Syntax 1
        • <Page ... xmlns:foo="clr-namespace:MyNS;assembly=MyAssembly">
      • Old Syntax 2
        • <?Mapping ClrNamespace="MyNS" XmlNamespace="local" ?>
        • <Page ... xmlns:foo="local">
      • Replacement Syntax 2
        • <Page ... xmlns:foo="clr-namespace:MyNS">
    • Ensure all RowDefintion and ColumnDefinition elements are not direct children of Grid.  They must be in a Grid.RowDefinitions or Grid.ColumnDefinitions property element.

    Note: don't do this until the FebCTP is out...Those URIs won't work in the Jan CTP.

    To download this tool, please see: http://robrelyea.com/tools/XamlMigrate/

    PostTypeIcon
    30,384 Views
  • WPF Attached Properties

    Filed under:

    post on the Avalon Forum from Jaffi raised a question

    WPF is not straight forward. Simple actions, like setting rectangles X position, requires using myRectange.SetValue(Canvas.LeftProperty, Value). I'm sure there is a performance penalty for such use (Which caused the performance problem).

    Why can't it be simple as myRectangle.X = value.

     

    That is why Every simple action I'm looking for require hours of searching

     

    What were those WPF folks thinking?

    We tried to balance extensibility and usability in WPF.  There are new concepts, we hope to make them easy to learn and make sense once you learn them.

     

    Reason for Attached properties:

    When dealing with out Layout system, we want to provide the ability for anybody to build new Panels.  Inside of those panels you should be able to put normal elements:

     

    <my:RobPanel>

       <Button />

       <Button />

    </my:RobPanel>

     

    Often, the new panel will need to define a property that the user can place on the children of that panel to control how the panel arranges the children.

     

    <my:RobPanel>

       <Button RotationsPerMinute="60" />

       <Button RotationsPerMinute="3" />

    </my:RobPanel>

    Unfortunately that won't work.  RotationsPerMinute is a newly invented property.  The Button class shipped before the RobPanel was ever built and the Button class designers forgot to include this important property!

     

    So WPF has the concept of attached properties.  One class defines the property.  You attach it to instances of other objects.

    <my:RobPanel>

       <Button Name="b1" my:RobPanel.RotationsPerMinute="60" />

       <Button Name="b2" my:RobPanel.RotationsPerMinute="3" />

    </my:RobPanel>

     

    The challenge is how can you expose this to developers now.

    RobPanel.SetRotatationsPerMinute(b1, 30);

     

    int currentRotationsPerMinute = RobPanel.GetRotationsPerMinute(b1);

     

    So if you buy the need for this extensibility, then you need to ask why is Canvas.Top and Canvas.Left modeled as an attached property, but Height and Width are modeled as normal properties.

    Top and Left are modeled as attached properties because they are only respected inside of a Canvas.  If I set Top or Left on a Button inside a StackPanel or DockPanel, it would have no effect.

     

    Object Model should Function

    We feel it is very bad form to have a number of methods or propeties on an object that actually don't do anything.

    My work with DHTML + CSS left me frustrated.  I could set any of the ~200 (?) style properties on any element.  Unfortunately I could never tell if it was supposed to work or not.

     

    Performance Penalty

    Jaffi asked if the static method syntax was a performance problem.

    There is cost, but marginal cost between a Top property defined on an element and an attached property Top defined on the panel.

     

    In WPF, regardless of attached vs. normal, most properties need some special capabilities: databinding, setting via style, animation, etc.

    The property system that enables this is something that is perf critical.  That is probably why we have reimplemented it 3-4 times during our development.

     

    Other Links

    A few more places to go learn about Attached Properties:

    PostTypeIcon
    59,223 Views
  • XAML Markup Extensions

    Filed under: ,

    Markup Extensions are documented in the Windows SDK here.

    In addition to what that document says, you can also use Markup Extensions as elements.  Not just in attributes.

    Somebody asked a question if you could have a tag map to an interface...the answer is no.  But you can have a tag map to a markup extension and do what ever you want in there.  This is a quick example of that.

    I've built a sample MarkupExtension called ClassFactory and added it my small set of downloadable samples.

    Here is a picture of this demo:

     

    XAML\MEasOE.xaml

    ...
        <Button>
          <RadioButton>test button</RadioButton>
        </Button>
        <Button>
          <Button.Content>
            <!-- Button.Content should not be necessary, but a bug requires it in this build-->
            <my:ClassFactory Type="RadioButton">
              <my:ClassFactory.Properties>
                <my:NameValuePair Name="Content" Value="Test button 2" />
              </my:ClassFactory.Properties>
            </my:ClassFactory>
          </Button.Content>
        </Button>
    ...

    ClassFactory.cs

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Windows.Serialization;
    using System.Reflection;

    namespace WpfDemos.XAML
    {
        public class ClassFactory : MarkupExtension
        {
            public ClassFactory()
            {
            }
            private Type _Type;
            public Type Type
            {
                get { return _Type; }
                set { _Type = value; }
            }
            private List<NameValuePair> _Properties;
            public List<NameValuePair> Properties
            {
                get
                {
                    if (_Properties == null)
                        _Properties = new List<NameValuePair>();
                    return _Properties;
                }
            }

            //Provide value is called and the return value is used by
            //the XamlReader instead of the MarkupExtension.
            //This could be used to do additional work that normal XamlReading rules don't
            //support.
            public override object ProvideValue(object targetObject, object targetProperty)
            {
                object o =  Type.Assembly.CreateInstance(Type.FullName);
                foreach (NameValuePair prop in Properties)
                {
                    PropertyInfo pi = Type.GetProperty(prop.Name);
                    //This would need to add typeconverter support to set types that aren't
                    //assignable by strings.
                    pi.SetValue(o, prop.Value, null);
                }
                return o;
            }

        }
    }

    PostTypeIcon
    20,586 Views