Farr far away....

gary farr's blog
in

June 2009 - Posts

Better XAML By Farr: WPF Line of Business Seminar

The WPF Line of Business seminar is a two day introductory provided by Microsoft outlining WPF, its benefits, architectural patterns practiced, and coding tips within line of business development.  After developing in WPF for over a year I thought this would be a good seminar to attend to gage where I am at as far as WPF development.  Well, I am very happy to find I follow very similar techniques and patterns as the Microsoft WPF experts Karl Shifflett and Jaime Rodriguez.  The seminar took place on June 12th and 13th at the Sheraton in Arlington Heights, IL. 

Well, I missed day one, which I don’t necessarily feel is bad for me.  It went over very basic fundamentals of WPF and XAML.  Below was the agenda I obviously missed.

  • 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
    So I wasn’t even supposed to go to Day Two however mother nature helped me out.  I had a baseball game at a minor league stadium, didn’t really want to miss that even if it would give me the opportunity to meet Karl Shifflett.  But rain washed that away and I went to Day Two.  Of course, I was late.  You can’t blame me.  9:00 on a Saturday morning in a suburb that is an hour away from the city and having five hours of sleep, well it was tough.  Below is the agenda I actually took part in.
  • 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

    Karl Shifflett was the first presenter, and if you read my previous posts on XAML, I have been reading his blogs for a long time and can say they have helped changed my perception of development in WPF.   I am going to summarize what he talked about as I am extremely tired after a long day of listening….  Karl talked about Databinding and how powerful it is.  Databinding is basically WPF 101.  He then talked about specific XAML features such as DataTemplates, ControlTemplates, ItemTemplates, ItemsPresenter, ValueConverters, and DataTempleteSelectors.  I love ValueConverters but you do have to be careful not to overuse them.  Basically, you need to decide whether to create a ValueConverter or convert parameters within the View Model itself.  My rule is if a converter is needed in multiple Views then it warrants a ValueConverter, however if it is a date conversion for a specific view, it should be placed in the View Model.  He briefly talked about data triggers, which Jaime would later say shouldn’t be used.  Sorry Jaime I would disagree with that statement.  I believe there is a separation between Business Logic and Design Logic and Data Triggers are completely valid for Design Logic. 

    Here are some things I learned from Karl:

    DataTemplateSelectors -  I don’t think they are necessary.  You are basically creating a resource outside your View-ViewModel relation and I feel that this can be contained within this relation view DataTemplates, binding, and DataTriggers.

    CollectionViewSource – Represents a layer on top of the binding source collection.  It allows sorting, filtering, and grouping of data before being displayed in a view.  Very, very cool….

    Debug of Data Binding – Karl talked about an interesting way to debug data binding a little further.  By adding System.Diagnostics and Trace levels to a binding source the output can display more detailed information if a binding error occurred.  Below is an example of how this can be implemented.

       1: <Window
       2:   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       3:   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       4:   xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
       5:  
       6: <TextBox.Text>
       7:        <Binding Source="{StaticResource myDataSource}" Path="PersonName"
       8:                 diag:PresentationTraceSources.TraceLevel="High"/>
       9:  </TextBox.Text>

    Jaime Rodriguez was the next presenter and started his presentation giving an architectural perspective of the MVVM pattern.  I was happy he gave props to Martin Fowler, one of the founding architects of this pattern.  Jaime explained the concept of MVVM and the idea behind the separation between Views and Models.  He also talked about the benefits of MVVM such as modularity, loosely coupled code, and testability. 

    Jaime next talked extensively about Commands.  He discussed RelayCommands, DelegateCommands, and the DelegateCommand in the MVVM Tool kit.  Commands are very important to binding in that they enable you to route events from Views to ViewModels.  The benefit of this is that you do not have to write any code behind in the view and your business logic from a command is separate from your design.   I have used RelayCommands and DelegateCommands in the past.  Relay Commands use CommandManager which provides command related utility methods that register command bindings.  DelegateCommands are part of PRISM, so to use DelegateCommands you need to add the Microsoft.Practices.Composite.dll.  DelegateCommands in the MVVM Tool kit are quite interesting as you do not need a Command Manager nor the Microsoft.Practices.Composite.dll.  I definitely have to play with this a little more.

  • Karl finished with some talk about Validation in WPF.   Karl gave examples of when to use validation in XAML and when to apply validation to business layer development.  He also talked about his Ocean Framework and validation using an AdornerElementPlaceHolder.  AdornerElementPlaceHolders are used for custom validation templates to provide visual feedback when a user input is not valid.  Basically, the add validation capabilities within XAML.

    Well, I know this post is a little overdue as the seminar was a week and a half ago.  But I finally am able to get it out there.  If you need more information about Jaime and Karl you can view their respective blogs,  Jaime, and Karl.  They both have information about the WPF LOB seminar in Chicago which includes demos and slides. 

    Better XAML By FARR: Animations, Resources Vs. Code Behind

    Animations are a feature in WPF and Silverlight that greatly enhance the user experience of the application.  Animations provide a smooth transition from one scene or view to the next and can significantly improve the overall composition and flow of that application.  Animations in WPF, currently are time based which means an animation will start and stop based on your computer system clock.  This, at times, could be an issue if your processor is experiencing excessive usage, your animation might skip frames thus resulting in choppy and less fluid animations. 

    In XAML, animations are created using a storyboards which can either be defined in XAML or code behind.  Please refer to the MSDN explanation of animations for more of an introductory.  This post details when it is a good time to create a storyboard as a resource in XAML and when it is more beneficial to create a storyboard in code behind.  

    XAML Storyboards

    For most cases, such as dealing with opacity, brush, or simplistic transform animations, storyboards can and should be created in XAML.  Below is a simple example of a storyboard that animates the three parts described.

       1: <Storyboard x:Key="LoadAnimation">
       2:         <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="grid" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
       3:             <SplineDoubleKeyFrame KeySpline="0,0,0,1" KeyTime="00:00:00" Value="0.5"/>
       4:             <SplineDoubleKeyFrame KeySpline="0.782,0,0,1" KeyTime="00:00:00.3000000" Value="1.1"/>
       5:             <SplineDoubleKeyFrame KeySpline="0,0,0,1" KeyTime="00:00:00.6000000" Value="1"/>
       6:         </DoubleAnimationUsingKeyFrames>
       7:         <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="grid" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
       8:             <SplineDoubleKeyFrame KeySpline="0,0,0,1" KeyTime="00:00:00" Value="0.75"/>
       9:             <SplineDoubleKeyFrame KeySpline="0.782,0,0,1" KeyTime="00:00:00.3000000" Value="1.1"/>
      10:             <SplineDoubleKeyFrame KeySpline="0,0,0,1" KeyTime="00:00:00.6000000" Value="1"/>
      11:         </DoubleAnimationUsingKeyFrames>
      12:         <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="txtTitle" Storyboard.TargetProperty="(UIElement.Opacity)">
      13:             <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0" KeySpline="1,0,1,1"/>
      14:             <SplineDoubleKeyFrame KeyTime="00:00:00.6000000" Value="1" KeySpline="1,0,1,1"/>
      15:         <ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="rectangle" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
      16:             <SplineColorKeyFrame KeyTime="00:00:00" Value="#CC333333"/>
      17:             <SplineColorKeyFrame KeyTime="00:00:00.4000000" Value="Black"/>
      18:         </ColorAnimationUsingKeyFrames>
      19: </Storyboard>

    Now if you remember from my previous blog, Resource Dictionaries Vs. User Control Resources, this resource can either be in a resource dictionary that all XAML files can have access to or in a specific User Controls resource.  My example above is actually taken from a Resource Dictionary because I have multiple views load using this animation. 

    Code-Behind Storyboards

    So when is it a good time to create code behind storyboards?  Well, I have found it is easier to create storyboards in code behind when you are dealing with any sort of animation that requires run time decided parameters to be passed into it.  That is not to say this cannot be achieved in XAML as well, but a rule I follow is that any logic determinant code should be in code behind, controllers, or view models.  One thing to remember, code behind storyboards should be contained within some User control code behind itself or a base control code behind.  A lot of people are moving towards the MV-VM pattern and a rule of thumb is that anything to do with design altering should be within the View and not the View Model.  Below is an example on my application where I calculate the animation trajectory of an image. 

       1: private void BeginIndicatorAnimation()
       2:        {
       3:            Storyboard indicatorStoryboard = new Storyboard();
       4:  
       5:            _animatedImage = new Image();
       6:            _animatedImage.Source = _indicatoritems.IndicatorSmallImage;
       7:            _animatedImage.Height = 200;
       8:            _animatedImage.Width = 200;
       9:            _animatedImage.VerticalAlignment = VerticalAlignment.Top;
      10:            _animatedImage.HorizontalAlignment = HorizontalAlignment.Left;
      11:            _animatedImage.Margin = new Thickness(0, 0, 0, 0);
      12:  
      13:            Grid grid = (Grid)this.FindName("grid");
      14:            ConvertTargetToImage(grid);
      15:  
      16:            grid.Children.Add(_animatedImage);
      17:  
      18:            System.Windows.Markup.INameScope currentNameScope = NameScope.GetNameScope(this);
      19:            NameScope.SetNameScope(this, new NameScope());
      20:  
      21:            _animatedImage.Name = "adornLayer";
      22:            this.RegisterName(_animatedImage.Name, _animatedImage);
      23:  
      24:            TranslateTransform animatedTranslateTransform = new TranslateTransform();
      25:            this.RegisterName("AnimatedTranslateTransform", animatedTranslateTransform);
      26:  
      27:            ScaleTransform animatedScaleTransform = new ScaleTransform();
      28:            this.RegisterName("AnimatedScaleTransform", animatedScaleTransform);
      29:  
      30:            TransformGroup transformGroup = new TransformGroup();
      31:            transformGroup.Children.Add(animatedScaleTransform);
      32:            transformGroup.Children.Add(animatedTranslateTransform);
      33:  
      34:            _animatedImage.RenderTransformOrigin = new Point(0.5, 0.5);
      35:            _animatedImage.RenderTransform = transformGroup;
      36:  
      37:            //Create Animation Path
      38:            PathGeometry pathGeometry = new PathGeometry();
      39:            PathFigure pathFigure = new PathFigure();
      40:  
      41:            double x = (CurrentPosition.X - (_animatedImage.Width / 2));
      42:            double y = (CurrentPosition.Y - (_animatedImage.Height / 2));
      43:  
      44:            pathFigure.StartPoint = new Point(x, y);
      45:            pathFigure.Segments.Add(new LineSegment(new Point(980 - 120 * (_indicatoritems.MealIndicatorCount - ++_indicatoritems.CurrentIndex), 90), true));
      46:  
      47:            pathGeometry.Figures.Add(pathFigure);
      48:            pathGeometry.Freeze();
      49:  
      50:            //Create Animation
      51:            //Opactiy 
      52:            DoubleAnimation opacityAnimation = new DoubleAnimation();
      53:            opacityAnimation.From = 1.0;
      54:            opacityAnimation.To = 0.0;
      55:            opacityAnimation.AccelerationRatio = 1.0;
      56:            opacityAnimation.Duration = new Duration(TimeSpan.FromSeconds(1.0));
      57:            Storyboard.SetTargetName(opacityAnimation, _animatedImage.Name);
      58:            Storyboard.SetTargetProperty(opacityAnimation, new PropertyPath(Image.OpacityProperty));
      59:  
      60:            //translate X to Path
      61:            DoubleAnimationUsingPath translateXAnimation = new DoubleAnimationUsingPath();
      62:            translateXAnimation.PathGeometry = pathGeometry;
      63:            translateXAnimation.Duration = TimeSpan.FromSeconds(1.0);
      64:            translateXAnimation.Source = PathAnimationSource.X;
      65:            translateXAnimation.AccelerationRatio = 1.0;
      66:  
      67:            Storyboard.SetTargetName(translateXAnimation, "AnimatedTranslateTransform");
      68:            Storyboard.SetTargetProperty(translateXAnimation,
      69:                new PropertyPath(TranslateTransform.XProperty));
      70:  
      71:            //Translate Y to Path
      72:            DoubleAnimationUsingPath translateYAnimation = new DoubleAnimationUsingPath();
      73:            translateYAnimation.PathGeometry = pathGeometry;
      74:            translateYAnimation.Duration = TimeSpan.FromSeconds(1.0);
      75:            translateYAnimation.Source = PathAnimationSource.Y;
      76:  
      77:            Storyboard.SetTargetName(translateYAnimation, "AnimatedTranslateTransform");
      78:            Storyboard.SetTargetProperty(translateYAnimation,
      79:                new PropertyPath(TranslateTransform.YProperty));
      80:  
      81:            DoubleAnimation scaleXAnimation = new DoubleAnimation(0.4, new Duration(TimeSpan.FromSeconds(1.1)));
      82:            Storyboard.SetTargetName(scaleXAnimation, "AnimatedScaleTransform");
      83:            Storyboard.SetTargetProperty(scaleXAnimation, new PropertyPath(ScaleTransform.ScaleXProperty));
      84:  
      85:            DoubleAnimation scaleYAnimation = new DoubleAnimation(0.4, new Duration(TimeSpan.FromSeconds(1.1)));
      86:            Storyboard.SetTargetName(scaleYAnimation, "AnimatedScaleTransform");
      87:            Storyboard.SetTargetProperty(scaleYAnimation, new PropertyPath(ScaleTransform.ScaleYProperty));
      88:  
      89:            indicatorStoryboard.Children.Clear();
      90:            indicatorStoryboard.Children.Add(scaleXAnimation);
      91:            indicatorStoryboard.Children.Add(scaleYAnimation);
      92:            indicatorStoryboard.Children.Add(translateXAnimation);
      93:            indicatorStoryboard.Children.Add(translateYAnimation);
      94:            indicatorStoryboard.Children.Add(opacityAnimation);
      95:            indicatorStoryboard.FillBehavior = FillBehavior.Stop;
      96:  
      97:            TimeSpan s = indicatorStoryboard.Children.Max(z => z.Duration.TimeSpan);
      98:            EventAggregator.GetEvent<HitTestDelayEvent>().Publish(s);
      99:  
     100:            _sbPopupAnimation = indicatorStoryboard.Clone();
     101:            _sbPopupAnimation.Name = "Indicator";
     102:            _sbPopupAnimation.Completed += PopupStoryBoardEndCompleted;
     103:            _sbPopupAnimation.Begin(this);
     104:  
     105:            NameScope.SetNameScope(this, currentNameScope);
     106:        }

    The code snippet above details an animation when a user clicks on a button within a screen and creates an image that is animated to a list of indicators somewhere arbitrarily on the screen.  As the image is animating, its size is being scaled down.  The pathFigure is a calculation that determines the starting point and ending point as well as the trajectory of the image during animation. 

    Conclusion

    As developers, we probably feel more comfortable creating animations in code behind.  I know i do.  However, I would say probably 85% of the animations I generally create are setup in XAML.  One way that makes the decision of where to put animations easier is to ask yourself, is my animation related to design or logic?  XAML - design, code behind – business logic.  If its design (UIElement updates and manipulations) then the animation should be in XAML.  If its logic (animations determined by some runtime property or calculation) then the animation should be in code behind. 

    Better XAML By FARR: Resource Dictionaries Vs User Control Resources

    A while ago I had a debate with my co-worker on when to put a resource in a User Control (whether it would be in XAML or in code behind) or put that resource in a Resource Dictionary.  We had this debate because we initially put all our resources in Resource Dictionaries and as our application became more modular this would become a problem when we only want to update a particular section’s resource.  Since all our resources were in the same location (our shell project) if a change was necessary, the shell project would also need to be updated.  I debated that it was nice to have all resources centrally located.  He claimed there were times a resource should be centrally located (when its accessed by multiple controls in multiple projects) and times when it should be directly tied to a particular control.  After a while of discussing back and forth the pros and cons of both, I finally sided with him on the following criteria. 

    • Resource Dictionary
      • If multiple controls in a solution need to access a resource then it should be put in a Resource Dictionary
    • User Control Resource
      • If a resource is specific to that User Control (for example a specific animation that is only performs within a specific User Control) then it should be put in the User Control’s Resource section.

    These rules may be simple, but as an application grows it is very easy to overlook this scope for resources and especially since resources aren’t the easiest to debug, this can easily create chaos in future development.

    So are there cases where this scope may not work for an application?  (Where I was right?) Sure!  When discussing this topic with one of our designers, he said it would be much easier for him to update all resources if they were in a centralized location.  Designers using Expression Blend do not really want to go through an entire application to find assets they need to update.  As we move further towards the direction of designer/developer collaboration, we must change our development techniques somewhat to coincide with a designer’s techniques. 

    In conclusion, As a developer, I have become fan of specifically defining resources as there is no reason for all controls to have access to them, however I do understand there may be a need to have a centralized location for resource.  Being consistent is the most important thing.  Whether you divide resources into sections or keep them all in the same Resource Dictionaries, you must stay consistent with the scope you define. 

    Better XAML By FARR

    For the last year and a half I have been working extensively on WPF applications.  During this time I have learned a great deal in architecting, coding and improving WPF application design and development.  This will be my first of a series of blog posts detailing my knowledge gained.  One may ask why it has taken so long to begin blogging about this topic?  I can answer with one word, laziness.  Yes, I have been lazy when it comes to blogging about the things I have learned, however, it is better late then never I presume.  So this post is to detail my future blog intentions.  Some of the topics I will cover are Resources and Animations, the Modelview-ViewModel pattern, PRISM, Attached Properties, and VisualsHelpers. 

    To start things off though, below are some links to WPF blogs I read religiously.  I have learned a lot from these blogs and feel they are a fabulous starting point for anyone really trying to get deep into WPF development. 

    Karl Shifflett: Karl on WPF

    I have probably learned more from Karl’s blog posts than any other.  If you start anywhere, start with Karl’s posts.

    Josh Smith:  Josh Smith on WPF

    Josh is also a must for blog reading. As my co-worker would say, he was doing Command binding before you were born.

    WPF Disciples 

    A collection of blogs from some of the most hard-core WPF developers out there.  Very cool stuff.

    Bea Stollnitz

    Though she blogs about Silverlight now, she has some of the best posts on data binding out there. 

    As for books, we call Windows Presentation Foundation Unleashed the Bible here at work.  I can’t say enough about how great this book is, not just for beginners in WPF, but for people who have been developing in WPF for a while as well.