Tag: C#

  • Real World: Unit Testing Queries Against Entity Framework (EF) Model / Repositories

    Real World: Unit Testing Queries Against Entity Framework (EF) Model / Repositories

    Unit testing is a tricky beast. As with all unit tests it is important to abstract any dependencies – so in the case of EF it’s the data persistence source. This must be handled carefully because EF creates a container that performs the interaction with the data source. Abstracting that container (via mocking or stubbing) is painfully hard.

    There are a few approaches for doing this, this is mine. I’m using the following tooling:

    The pattern uses the following DAL class structure (like a pseudo-repository pattern against an example Product database table):

    • ProductDataRepository: IProductDataRepository – A thin layer to EF, returns only IQueryable<T> types from raw EF lookups. No filters, sorting or other queries are applied here as this class is not unit testable. This class internal to the DAL assembly.
    • ProductRepository(IProductDataRepository repos) – Constructor takes an instance of the IProductDataRepository interface, and uses this for executing specific queries against the base IQueryable<T> values. This class is exposed for external calls. This is unit-tested.

    The unit tests can use Moles to stub an instance of IProductDataRepository (delegating the internal Get… methods to returning a hard coded collection of test data) that is then passed to the instance of ProductRepository under test.

    Looking at these classes from the bottom up, as an example:

    ProductDataRepository

    To Provide a thin layer that only returns IQueryable<T> (our example also filters out deleted rows):

    public class ProductDataRepository : IProductDataRepository {
    
    private MyDatabase_ModelContainer _model;
    protected internal MyDatabase_ModelContainer Model {
    get {
    if (_model == null) {
    _model = new MyDatabase_ModelContainer();
    }
    return _model;
    }
    }
    
    public IQueryable<product> GetProducts() {
    return Model.Products.Where(p => p.IsTombstoned == false);
    }
    }
    

    ProductRepository

    Core Requirement: Provide the implementation and execution of the data lookup. Consumes an instance of IProductDataRepository via constructor injection.

    public class ProductRepository{
    public ProductRepository() : this(new ProductDataRepository()) {
    }
    
    private IProductDataRepository _mRepository;
    public ProductRepository (IProductDataRepository iRepository) {
    _mRepository = iRepository;
    }
    
    public Product GetProduct(String productKey) {
    return mRepository.GetProducts().FirstOrDefault(p => p.ProductKey.Contains(productKey));
    }
    
    public List<Product> GetProducts (String productKey) {
    return mRepository.GetProducts().Where(p => p.ProductKey.Contains(productKey).ToList();
    }
    }
    

    So, we can see that this is making calls to:

    mRepository.GetProducts()

    Which returns an IQueryable<T> type, then implements required functionality:

    .Where(p => p.ProductKey.Contains(productKey))

    and then executes the Query:

    .ToList();

    GetProductsTest

    To test the ProductRepository we can create an instance and stub the IProductDataRepository. The mocking and standard setup is done in an abstract class, to provide reusability for other tests that may require this functionality:

        [TestClass]
    public abstract class ProductTestContext
    {
    private IProductDataRepository _dataRepository;
    private IProductDataRepository DataRepository
    {
    get {
    if (_dataRepository == null) {
    _dataRepository = new SIProductDataRepository() {
    GetProducts = () => Products.AsQueryable()
    };
    }
    return _dataRepository;
    }
    }
    
    private ProductRepository _ProductRepository;
    public ProductRepository ProductRepository
    {
    get {
    if (_ProductRepository == null) {
    _ProductRepository = new ProductRepository(DataRepository);
    }
    return _ProductRepository;
    }
    }
    
    private List<Product> _products;
    public List<Product> Products
    {
    get {
    if (_products == null) {
    _products = new List<Product>();
    
    for (int i = 1; i <= 9; i++) {
    _products.Add(new Product(){ ProductKey = "MyKey" + i });
    }
    }
    return _products;
    }
    }
    
    }
    

    So, here we can see the IProductDataRepository readonly property returns a stubbed instance new new SIProductDataRepository. This stub is generated by the Moles framework (see Moles documentation on how to do this). During the creation of this object we delegate the GetVouchers method to return the concrete (and hardcoded because this is a unit test) instance of Products.AsQueryable():

    GetProducts = () => Products.AsQueryable()

    The .AsQueryable() is essential to insure the instance of IProductDataRepository, that is used during the test, returns the same type as the instance used in the real world.

    Now our unit test class can inherit ProductTestContext and Arrange, Act and Assert the required tests easily:

        [TestClass]
    public class GetProductsTest : ProductTestContext
    {
    
    [TestMethod]
    public void GetSingleProduct()
    {
    // repeat the test for each instance in the test collection
    for (int i = 1; i <= 9; i++) {
    // Arrange – most of the Arrangement is done in the abstract
    var goodProductKey = "MyKey" + i;
    
    // Act – on the abstract instance of ProductRepository,
    //            which is using the stubbed instance of ProductDataRepository
    var product = ProductRepository.GetProduct(goodProductKey);
    
    // Assert – make sure the correct product is returned from the stubbed data
    Assert.IsNotNull(product);
    Assert.IsTrue(product.ProductKey.Equals(goodProductKey));
    }
    }
    
    [TestMethod]
    public void GetIndivudalFilteredProducts()
    {
    // repeat the test for each instance in the test collection
    for (int i = 1; i <= 9; i++) {
    // Arrange – most of the Arrangement is done in the abstract
    var goodProductKey = "MyKey" + i;
    
    // Act – on the abstract instance of ProductRepository,
    //            which is using the stubbed instance of ProductDataRepository
    var products = ProductRepository.GetProducts(goodProductKey);
    
    // Assert – make sure the correct products are returned from the stubbed data
    Assert.IsNotNull(products);
    Assert.IsTrue(products.Count == 1);
    }
    }
    
    [TestMethod]
    public void GetMultipleFilteredProducts()
    {
    // Expectation – all the results in the abstract Products collection should be returned
    var expectation = Products.Count;
    
    // Arrange – most of the Arrangement is done in the abstract
    var goodProductKey = "MyKey";
    
    // Act – on the abstract instance of ProductRepository,
    //            which is using the stubbed instance of ProductDataRepository
    var products = ProductRepository.GetProducts(goodProductKey);
    
    // Assert – make sure the correct products are returned from the stubbed data
    Assert.IsNotNull(products);
    Assert.AreEqual(expectation, products.Count);
    }
    }
    
  • Silverlight Deferred / Delayed Selected Date Picker

    Silverlight Deferred / Delayed Selected Date Picker

    When implementing a date picker that is used to fetch some ‘details’ based on the selected date, the chances are that you don’t want to begin fetching the ‘details’ immediately.

    If you did, and made a rapid change to the SelectedDate (maybe holding down an arrow key), the asynchronous fetch will be repeated a large number of times.

    To prevent this, implement a deferral on the selected date change, for example:

    public class DeferredDP : DatePicker {
    
    public DeferredDP() {
    this.DefaultStyleKey = typeof(DatePicker);
    base.SelectedDateChanged += new EventHandler(DeferredDP_SelectedDateChanged);
    }
    
    DispatcherTimer _timer;
    
    void DeferredDP_SelectedDateChanged(object sender, SelectionChangedEventArgs e) {
    /// if there is an instance of the timer already running stop it.
    if (_timer != null) {
    _timer.Stop();
    _timer = null;
    }
    
    /// only trigger the selection changed event when the date has been changed
    if (e.AddedItems.Count == 1 &&
    e.AddedItems[0] is DateTime) {
    
    if (SelectionDelay.HasValue) {
    /// if the timer delay has been set, delay the setting of the value
    _timer = new DispatcherTimer();
    _timer.Interval = new TimeSpan(0,0,0,0,SelectionDelay.Value);
    _timer.Tick += (s1, e1) => {
    SetValue(SelectedDateDeferredProperty, (DateTime)e.AddedItems[0]);
    if (_timer != null) {
    _timer.Stop();
    _timer = null;
    }
    };
    _timer.Start();
    } else { // if the timer delay is not set, set the property immediately.
    SetValue(SelectedDateDeferredProperty, (DateTime)e.AddedItems[0]);
    }
    }
    }
    
    ///
    /// Milliseconds delay before the selected date value is updated.
    ///
    public int? SelectionDelay {
    get { return (int?)GetValue(SelectionDelayProperty); }
    set { SetValue(SelectionDelayProperty, value); }
    }
    
    public static readonly DependencyProperty SelectionDelayProperty =
    DependencyProperty.Register("SelectionDelay", typeof(int?), typeof(DeferredDP), new PropertyMetadata(null));
    
    public DateTime? SelectedDateDeferred {
    get { return (DateTime?)GetValue(SelectedDateDeferredProperty); }
    set { SetValue(SelectedDateDeferredProperty, value); }
    }
    
    public static readonly DependencyProperty SelectedDateDeferredProperty =
    DependencyProperty.Register("SelectedDateDeferred", typeof(DateTime?), typeof(DeferredDP), new PropertyMetadata(null, SelectedDateDeferredChanged));
    public static void SelectedDateDeferredChanged(DependencyObject d, DependencyPropertyChangedEventArgs args) {
    DeferredDP instance = d as DeferredDP;
    
    if (instance.SelectedDateDeferred != instance.SelectedDateDeferred) {
    instance.SelectedDateDeferred = instance.SelectedDateDeferred;
    }
    
    }
    }
    
  • Regex hints #1

    I love the power of regular expressions to do highly repetitive work for me, but I don’t use them frequently enough to remember the exacting intricacies of the syntax. Time for a series of posts with examples that have worked for me.

    First up, is the conversion of standard properties to notification properties.

    This can be used to convert all of our vanilla DTO’s into useable Silverlight backing stores 🙂

    • find: public {(:a)+} {(:a)+} \{ get\; set\; \}{$}
    • replace: public \1 \2 {\n get { return _\2; }\n set { SetValue(ref _\2, value, "\2"); }\n}\nprivate \1 _\2;

    So the Vanilla Class;

    public class VanillaClass
    {
    public int MyInt { get; set; }
    
    public int MySecondInt { get; set; }
    
    public string MyString { get; set; }
    
    public short MyShort { get; set; }
    
    public LinkTypeEnum MyEnum { get; set; }
    }

    Will be converted to the Triple Chocolate Class;

    public class VanillaClass
    {
    public int MyInt
    {
    get { return _MyInt; }
    set { SetValue(ref _MyInt, value, "MyInt"); }
    }
    private int _MyInt;
    
    public int MySecondInt
    {
    get { return _MySecondInt; }
    set { SetValue(ref _MySecondInt, value, "MySecondInt"); }
    }
    private int _MySecondInt;
    
    public string MyString
    {
    get { return _MyString; }
    set { SetValue(ref _MyString, value, "MyString"); }
    }
    private string _MyString;
    
    public short MyShort
    {
    get { return _MyShort; }
    set { SetValue(ref _MyShort, value, "MyShort"); }
    }
    private short _MyShort;
    
    public LinkTypeEnum MyEnum
    {
    get { return _MyEnum; }
    set { SetValue(ref _MyEnum, value, "MyEnum"); }
    }
    private LinkTypeEnum _MyEnum;
    }

    Obviously the SetValue method is part of a base class from which VanillaClass will inherit, but that is irrelevent, the object of this exercise is to remove the heavy lifting involved in converting the Properties to Notification Properties. Also, post-replace, I use the Visual Studio Auto Formatting settings to correctly beautify the new properties.

    Adding attributes into the mix is straightforward. For [DataMember()] handling use:

    Find: \[DataMember\(\)\]\n((:b)+)public {(:a)+} {(:a)+} \{ get\; set\; \}{$}

    Replace:[DataMember()]\npublic \1 \2 {\n get { return _\2; }\n set { SetValue(ref _\2, value, "\2"); }\n}\nprivate \1 _\2;

  • Silverlight Commands – Data grid row selected

    following on from http://thoughtjelly.blogspot.com/2009/09/silverlight-prism-commands-textchanged.html and in response to John Papa’s PDC talk http://johnpapa.net/silverlight/mvvm-and-prism-demo-for-pdc09-silverlight-session. Another highly useful command behaviour is for DataGridRowSelected.
    This also gets over the issues described here and here. The code (as written by John Papa) is:

    public class DataGridRowSelectedCommandBehavior : CommandBehaviorBase
    {
    public DataGridRowSelectedCommandBehavior(DataGrid selectableObject)
    : base(selectableObject)
    {
    selectableObject.SelectionChanged += OnSelectionChanged;
    }

    private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
    this.CommandParameter = this.TargetObject.SelectedItem;
    ExecuteCommand();
    }
    }

    And

    public static class DataGridRowSelected
    {
    private static readonly DependencyProperty DataGridRowSelectedCommandBehaviorProperty = DependencyProperty.RegisterAttached(
    "SelectedCommandBehavior",
    typeof(DataGridRowSelectedCommandBehavior),
    typeof(DataGridRowSelected),
    null);

    public static readonly DependencyProperty CommandProperty = DependencyProperty.RegisterAttached(
    "Command",
    typeof(ICommand),
    typeof(DataGridRowSelected),
    new PropertyMetadata(OnSetCommandCallback));

    public static void SetCommand(DataGrid dataGrid, ICommand command)
    {
    dataGrid.SetValue(CommandProperty, command);
    }

    public static ICommand GetCommand(DataGrid dataGrid)
    {
    return dataGrid.GetValue(CommandProperty) as ICommand;
    }

    private static void OnSetCommandCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
    {
    var dataGrid = dependencyObject as DataGrid;
    if (dataGrid != null)
    GetOrCreateBehavior(dataGrid).Command = e.NewValue as ICommand;
    }

    private static DataGridRowSelectedCommandBehavior GetOrCreateBehavior(DataGrid dataGrid)
    {
    var behavior = dataGrid.GetValue(DataGridRowSelectedCommandBehaviorProperty) as DataGridRowSelectedCommandBehavior;
    if (behavior == null)
    {
    behavior = new DataGridRowSelectedCommandBehavior(dataGrid);
    dataGrid.SetValue(DataGridRowSelectedCommandBehaviorProperty, behavior);
    }

    return behavior;
    }
    }
  • Data-binding Radio Buttons in Silverlight to Enum

    In Silverlight there is no Enum.Getvalue() method, so there is not out-of-the box way of databinding a radio buttongroup to an enumerable value in a viewmodel.

    Step forward converters.

    using System;
    using System.Windows.Data;
    namespace YourNamespace
    { public class EnumBoolConverter : IValueConverter
    { #region Methods
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    { if (value == null || parameter == null)
    return value;
    return value.ToString() == parameter.ToString();
    }
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
    if (value == null || parameter == null)
    return value;
    return Enum.Parse(targetType, (String)parameter, true);
    }
    #endregion Methods
    }
    }

    With the previous convertor it is then quite simple to bind the radio button list. Simply pass the Enum value (as a string) as the converter parameter, and you are away:

    <UserControl
    ...>

    <YourNamespace:EnumBoolConverter
    x:Key="ConvertEnum" />


    <RadioButton
    Content="Yes"
    GroupName="Group1"
    IsChecked="{Binding Path=UserOption, Mode=TwoWay, Converter={StaticResource ConvertEnum}, ConverterParameter=Yes}" />
    <RadioButton
    Content="No"
    GroupName="Group2"
    IsChecked="{Binding Path=UserOption, Mode=TwoWay, Converter={StaticResource ConvertEnum}, ConverterParameter=No}" />
    <RadioButton
    Content="Both"
    GroupName="Group3"
    IsChecked="{Binding Path=UserOption, Mode=TwoWay, Converter={StaticResource ConvertEnum}, ConverterParameter=Both}" />



    Also make sure the GroupName on each radio button is different or the system gets monumentally confused and throws a StackOverflowException.

  • Date issues in Silverlight

    Seeing some strange date behaviours in SL UI components. My local culture is UK but we keep seeing US dates popping up “here and there”.

    Have tried setting the Language= “en-GB” in the upper most control, also setting the thread culture is not effecting across the app.

    Going to have to get help on this one…

  • Restyling Transitions in the Silverlight Toolkit TransitioningContentControl

    (This post extends my example for using cross project merged dictionaries in Silverlight)

    I’m a developer, not a designer and as such using Expression Blend doesn’t feel natural and makes me feel dirty… However I had to bite the bullet to ease the restyling of the transition animation in the Toolkit TransitioningContentControl.

    NOTE: At time of writing this control is in the Experimental Quality Band – the way I have built this might not work in the future!!

    To edit the transition in blend I added a TCC to my page, right clicked and chose “Edit Template Edit a Copy… Define in Application

    You can then start editing the VisualStates. There is tons of information on how to do this, so I won’t repeat that here, but here are the basics:

    Select States tab, Choose a transition to edit (or add a new one) expand the objects and make changes to the states along the time line.

    After making changes to your template open it and examine the changes. Most stuff is pretty self explanatory. Once this is done I can close blend and copy the XAML in to Visual Studio – now I feel safe and clean!!

    So, I wanted to add a flip transition, that makes the page look like it is doing a 360 flip around a vertical axis. First thing to do is edit the content template to include project planes, as these are hooked from my new animation (lines 17-19 and 37-39 below). You won’t need to do this is you are changing basic animation properties (offset, opacity, scale etc):


    <ContentPresenter x:Name="PreviousContentPresentationSite"
    HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
    VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
    Content="{x:Null}"
    ContentTemplate="{TemplateBinding ContentTemplate}">















    <ContentPresenter x:Name="CurrentContentPresentationSite"
    HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
    VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
    Content="{x:Null}"
    ContentTemplate="{TemplateBinding ContentTemplate}">














    Then add my flip animation (lines 53-74 below):

    <Style x:Key="TransitioningContentControlStyle1"
    TargetType="layoutToolkit:TransitioningContentControl">
    <Setter Property="IsTabStop"
    Value="True" />
    <Setter Property="HorizontalContentAlignment"
    Value="Left" />
    <Setter Property="VerticalContentAlignment"
    Value="Top" />
    <Setter Property="Transition"
    Value="DefaultTransition" />



    <Border Background="{TemplateBinding Background}"
    BorderBrush="{TemplateBinding BorderBrush}"
    BorderThickness="{TemplateBinding BorderThickness}"
    CornerRadius="2">




    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="CurrentContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.Opacity)">
    <SplineDoubleKeyFrame KeyTime="00:00:00"
    Value="0" />
    <SplineDoubleKeyFrame KeyTime="00:00:00.300"
    Value="1" />

    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="PreviousContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.Opacity)">
    <SplineDoubleKeyFrame KeyTime="00:00:00"
    Value="1" />
    <SplineDoubleKeyFrame KeyTime="00:00:00.300"
    Value="0" />





    <ObjectAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="PreviousContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.Visibility)">


    Collapsed







    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="PreviousContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationY)">
    <EasingDoubleKeyFrame KeyTime="00:00:00"
    Value="0" />
    <EasingDoubleKeyFrame KeyTime="00:00:00.3000000"
    Value="90" />

    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="CurrentContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationY)">
    <EasingDoubleKeyFrame KeyTime="00:00:00"
    Value="-90" />
    <EasingDoubleKeyFrame KeyTime="00:00:00.3000000"
    Value="-90" />
    <EasingDoubleKeyFrame KeyTime="00:00:00.6000000"
    Value="0" />






    <ContentPresenter x:Name="PreviousContentPresentationSite"
    HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
    VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
    Content="{x:Null}"
    ContentTemplate="{TemplateBinding ContentTemplate}">















    <ContentPresenter x:Name="CurrentContentPresentationSite"
    HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
    VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
    Content="{x:Null}"
    ContentTemplate="{TemplateBinding ContentTemplate}">



















    NOTE: I have removed the DefaultTransition, UpTransition and DownTransition VisualStates from this code as I am not using them. Normal MUST remain. If you want these transition states back they are copied below for your convenience.

    Finally I copied this style to a separate file so it can be referenced as a MergedDictionary across a multi project solution (as described here).

    When doing this, remember to Add a reference to System.Windows.Controls.Toolkit and System.Windows.Controls.Layout.Toolkit from the resources project, and in the resource xaml file:

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:layoutToolkit="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Layout.Toolkit">

    DefaultTransition, UpTransition and DownTransition Visual States



    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="CurrentContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.Opacity)">
    <SplineDoubleKeyFrame KeyTime="00:00:00"
    Value="0" />
    <SplineDoubleKeyFrame KeyTime="00:00:00.300"
    Value="1" />

    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="PreviousContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.Opacity)">
    <SplineDoubleKeyFrame KeyTime="00:00:00"
    Value="1" />
    <SplineDoubleKeyFrame KeyTime="00:00:00.300"
    Value="0" />





    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="CurrentContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.Opacity)">
    <SplineDoubleKeyFrame KeyTime="00:00:00"
    Value="0" />
    <EasingDoubleKeyFrame KeyTime="00:00:00.7330000"
    Value="0" />
    <EasingDoubleKeyFrame KeyTime="00:00:01.1000000"
    Value="1" />

    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="PreviousContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.Opacity)">
    <SplineDoubleKeyFrame KeyTime="00:00:00"
    Value="1" />
    <EasingDoubleKeyFrame KeyTime="00:00:00.5000000"
    Value="1" />
    <SplineDoubleKeyFrame KeyTime="00:00:00.9000000"
    Value="0" />

    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="PreviousContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)">
    <EasingDoubleKeyFrame KeyTime="00:00:00"
    Value="0">




    <EasingDoubleKeyFrame KeyTime="00:00:00.5000000"
    Value="0">




    <EasingDoubleKeyFrame KeyTime="00:00:00.9000000"
    Value="0">





    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="CurrentContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
    <EasingDoubleKeyFrame KeyTime="00:00:00.7330000"
    Value="0" />
    <EasingDoubleKeyFrame KeyTime="00:00:01.1000000"
    Value="1" />

    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="CurrentContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
    <EasingDoubleKeyFrame KeyTime="00:00:00.7330000"
    Value="0" />
    <EasingDoubleKeyFrame KeyTime="00:00:01.1000000"
    Value="1" />

    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="PreviousContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
    <EasingDoubleKeyFrame KeyTime="00:00:00"
    Value="1">




    <EasingDoubleKeyFrame KeyTime="00:00:00.5000000"
    Value="0.75">




    <EasingDoubleKeyFrame KeyTime="00:00:00.9000000"
    Value="1">





    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="PreviousContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
    <EasingDoubleKeyFrame KeyTime="00:00:00"
    Value="1">




    <EasingDoubleKeyFrame KeyTime="00:00:00.5000000"
    Value="0.75">




    <EasingDoubleKeyFrame KeyTime="00:00:00.9000000"
    Value="1">





    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="PreviousContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
    <EasingDoubleKeyFrame KeyTime="00:00:00.5000000"
    Value="0">




    <EasingDoubleKeyFrame KeyTime="00:00:00.9000000"
    Value="-500">





    <PointAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="PreviousContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.RenderTransformOrigin)">
    <EasingPointKeyFrame KeyTime="00:00:00"
    Value="0.5,0.5" />
    <EasingPointKeyFrame KeyTime="00:00:00.5000000"
    Value="0.5,0.5" />

    <PointAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="CurrentContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.RenderTransformOrigin)">
    <EasingPointKeyFrame KeyTime="00:00:00"
    Value="0.5,0.5" />
    <EasingPointKeyFrame KeyTime="00:00:00.7330000"
    Value="0.5,0.5" />
    <EasingPointKeyFrame KeyTime="00:00:01.1000000"
    Value="0.5,0.5" />





    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="CurrentContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.Opacity)">
    <SplineDoubleKeyFrame KeyTime="00:00:00"
    Value="0" />
    <SplineDoubleKeyFrame KeyTime="00:00:00.300"
    Value="1" />

    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="CurrentContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)">
    <SplineDoubleKeyFrame KeyTime="00:00:00"
    Value="-40" />
    <SplineDoubleKeyFrame KeyTime="00:00:00.300"
    Value="0" />

    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="PreviousContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.Opacity)">
    <SplineDoubleKeyFrame KeyTime="00:00:00"
    Value="1" />
    <SplineDoubleKeyFrame KeyTime="00:00:00.300"
    Value="0" />

    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="PreviousContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)">
    <SplineDoubleKeyFrame KeyTime="00:00:00"
    Value="0" />
    <SplineDoubleKeyFrame KeyTime="00:00:00.300"
    Value="40" />


    Note: UpTransition has been altered to do a funky “drop-back-swing-left-and-fade-in” animation

    Example

    The obligatory example is here…

  • Cross Project MergedDictionaries in Silverlight

    Todd Miranda has posted a video on the use of merged dictionaries on the Learning portal of Silverlight.net (find it here). This video explains the concepts of MergedDictionaries in a very long winded way. IMHO people investigating MergedDictionaries will already know how to layout a grid, and play some simple controls, so the first 8m of the tutorial is pretty boring.

    The description of the use of MergedDictionaries is pretty good, along with a couple of common pitfalls, but this does not explain one core feature well enough: Cross Project

    Anyone writing a Silverlight LOB application is almost certainly going to have multiple projects, and the use of MergedDictionaries corss project is going to be a huge advantage.

    Luckily this isn’t much more difficult than Todd has shown. Imagine the following scenario; we have a bunch of silverlight pages that need to share styles, but are spread across a few different projects. We want to keep the styles (as resources) in one location and reference these.

    So simply create a Resources project, and add your resources files as described by Todd (Add | New Item… | XML file etc) (you can also add these to any sensible location in your existing solution – say a UserControls project)

    Then when referencing the MergedDictionary from the UserControl where the style will be applied, use the Assembly name of the resources location, rather than the assembly name of the UserControl location.

    So the Source value will be formatted as Source=”/[AssemblyName];component/[Path and filename]

    Don’t forget to add a reference to the Resources project from the Target Project.

    Further details and and example of this in action with a re-styled TransitioningContentControl can be found here: http://thoughtjelly.blogspot.com/2009/10/restyling-transitions-in-silverlight.html.

  • Walking the XAML VisualTree to find a parent of type

    To find a parent item of type T, you can use the following helper class:

    public static class DependencyObjectHelper
    {
    public static DependencyObject FindParent(this DependencyObject obj, Predicate where) {
    var parent = VisualTreeHelper.GetParent(obj);
    
    if (parent == null || where(parent)) {
    return parent;
    } else {
    return parent.FindParent(where);
    }
    }
    
    public static T FindParentOfType(this DependencyObject obj) where T : DependencyObject {
    return (T)FindParent(obj, x => x is T);
    }
    }

    This can then be utilised as follows:

    Grid item = ((DependencyObject)childObject).FindParentOfType();

    This was particularly useful when wanting to locate an invalid control from a ValidationSummary in silverlight, that was nested in an accordian panel:

    BIG shout out goes to Jedi Master Twist for the lead on this 🙂

  • .NET Debugging and Stack Trace

    When debugging enable the stack trace view to see where code has been triggered from. This is particularly useful for figuring out where events have been triggered from (delegation of event handlers from multiple places etc):