Tuesday, May 10, 2011

Transformation in WPF


In this article i am going to explain some basics about transformations in WPF. 

List of different transformation available in WPF

  • Rotate Transform
  • Scale Transform
  • Skew Transform
  • Translate Transform
  • Matrix Transform

Rotate Transform

Rotate transform rotates an element to the specified Angle. To rotate an element to specific degree you can specify value to Angle property of Rotate Transform class. You can also set negative value to rotate an element anticlockwise. You can use CenterX and CenterY properties to specify center point of rotation. By default it takes top left corner of an element as center point and relatively rotation will apply.

    <Canvas>
        <Rectangle Fill="blue" Height="75" Width="75" 
                   Canvas.Left="10" Canvas.Top="50" />
        <Rectangle Fill="blue" Height="75" Width="75" 
                   Canvas.Left="150" Canvas.Top="50">
            <Rectangle.RenderTransform>
                <RotateTransform Angle="25" />
            </Rectangle.RenderTransform>
        </Rectangle>
        <Rectangle Fill="blue" Height="75" Width="75" 
                   Canvas.Left="275" Canvas.Top="50">
            <Rectangle.RenderTransform>
                <RotateTransform Angle="-25" 
                                 CenterX="50" CenterY="50" />
            </Rectangle.RenderTransform>
        </Rectangle>
    </Canvas>



Scale Transform

Scale Transform scales an element by specified ScaleX and ScaleY values. ScaleX and ScaleY value resize the element. If you specify ScaleX to 1.5 then it will scales an element horizontally to 150 percent and same applies to ScaleY. You can also specify CenterX and CenterY properties to specify center point of Scale Transform.

    <Canvas>
        <Rectangle Fill="blue" Height="75" Width="75"
                   Canvas.Left="10" Canvas.Top="50" />
        <Rectangle Fill="blue" Height="75" Width="75"
                   Canvas.Left="150" Canvas.Top="50">
            <Rectangle.RenderTransform>
                <ScaleTransform ScaleX="0.5" ScaleY="0.5" />
            </Rectangle.RenderTransform>
        </Rectangle>
        <Rectangle Fill="blue" Height="75" Width="75" 
                   Canvas.Left="250" Canvas.Top="50">
            <Rectangle.RenderTransform>
                <ScaleTransform ScaleX="1.5" ScaleY="1.5" />
            </Rectangle.RenderTransform>
        </Rectangle>
    </Canvas>



Skew Transform

Skew Transform skews an element by specified AngleX and AngleY values. You can specify AngleX and AngleY properties to skew an element to the angle of x-axis and y-axis. You can also specify CenterX and CenterY properties to specify center point of Skew Transform.

    <Canvas>
        <Rectangle Fill="blue" Height="75" Width="75"
                   Canvas.Left="10" Canvas.Top="50" />
        <Rectangle Fill="blue" Height="75" Width="75"
                   Canvas.Left="120" Canvas.Top="50">
            <Rectangle.RenderTransform>
                <SkewTransform  AngleX="20" AngleY="20" />
            </Rectangle.RenderTransform>
        </Rectangle>
        <Rectangle Fill="blue" Height="75" Width="75"
                   Canvas.Left="250" Canvas.Top="50">
            <Rectangle.RenderTransform>
                <SkewTransform  AngleX="-20" AngleY="-20" 
                                CenterX="75" CenterY="75" />
            </Rectangle.RenderTransform>
        </Rectangle>
    </Canvas>





Translate Transform

Translate transform moves an element based on two X and Y property. It doesn’t move based on center position.  It simply moves an element horizontally(X) and vertically (Y) based on current position.

    <Canvas>
        <Rectangle Fill="blue" Height="75" Width="75" 
                   Canvas.Left="10" Canvas.Top="50" />
        <Rectangle Fill="blue" Height="75" Width="75" 
                   Canvas.Left="120" Canvas.Top="50">
            <Rectangle.RenderTransform>
                <TranslateTransform  X="30" Y="30" />
            </Rectangle.RenderTransform>
        </Rectangle>
    </Canvas>





Matrix Transform


It can be used to create custom 2D transformation. You can create custom transformation using Matrix Transformation which is not provided by above mentioned basic transformation (like Rotate, Scale, Skew and Translate Transformation). You can create Matrix Transformation by using M11, M12, M21, M22, OffsetX and OffsetY parameters. Where M11 and M22 are used to stretch an element, M12 and M21 are used to skew an element and OffsetX and OffsetY are used to position an element.

<Canvas>
        <Button Content="Matrix" Canvas.Top="20" Canvas.Left="20" >
            <Button.RenderTransform>
                <MatrixTransform>
                    <MatrixTransform.Matrix>
                        <Matrix M11="3" M22="3" M12="0.5"
M21="-0.5" OffsetX="20" OffsetY="1" />
                    </MatrixTransform.Matrix>
                </MatrixTransform>
            </Button.RenderTransform>
        </Button>
</Canvas>

You can also create Matrix Transformation by assigning simple string to RenderTransform like this (this applies to only Matrix Transformation).

<Button RenderTransform="3,0.5,-0.5,3,20,1"  
        Content="Matrix" Canvas.Top="20" Canvas.Left="20" />

Where the sequence of comma separated list will be M11, M12, M21, M22, OffsetX and OffsetY.






Multiple Transformations

You can apply multiple transformations to single element. To apply multiple transformations you need use TransformGroup class and inside TransformGroup you can add multiple Transform in it.

    <Canvas>
        <Button Content="Multiple Transformation" 
                Canvas.Top="40" Canvas.Left="20" Width="150" />
        <Button Content="Multiple Transformation"
                Canvas.Top="60" Canvas.Left="20" Width="150">
            <Button.RenderTransform>
                <TransformGroup>
                    <ScaleTransform ScaleX="1" ScaleY="-1" 
                                  CenterX="25" CenterY="12" />
                    <SkewTransform AngleX="10" />
                </TransformGroup>
            </Button.RenderTransform>
        </Button>
    </Canvas>

Hope, you like this post and also helps you to understand more about WPF Transformations. 


Please post your suggestion/queries/feedback in comments if any.

Friday, May 6, 2011

Virtualizing Stack Panel in WPF



To understand Virtualizing Stack Panel first we should understand about what is Virtualization in WPF.

Virtualization in WPF

In Virtualization, elements are created and maintained when they are visible. This also called as UI Virtualization in WPF. Let’s understand with an example.
Let’s assume we have Listbox control with 1 million items and we can see only 10 items at a time. So the only 10 items which are currently visible will get created and maintained by the Listbox. So instead of 1 million items loaded at a time on listbox control it loads only 10 items which are visible. This concept is called as UI Virtualization in WPF. By using Virtualization you will get better performance. In our example you can find performance improvements in loading of data and scrolling of items in listbox. 

VirtualizingStackPanel in WPF

The feature of Virtualization is implemented in VirtualizingStackPanel. It will work similar to the StackPanel and also virtualized its child items too.

By default VirtualizingStackPanel is implemented on ListBox, ListView and TreeView. You can manually enable or disable virtualization on Listbox control by setting VirtualizingStackPanel.IsVirtualizing property. Internally VirtualizingStackPanel creates item container for each visible item. When item is not visible it destroys that item container. So some times with huge data it is very expensive task to create and destroy item container for each visible item.

In dotnet framework 3.5 SP1 Microsoft introduced VirtualizationMode. If you set VirtualizingStackPanel.VirtualizationMode = “Recycling” then each container will get reuse instead of destroy. You will get better performance by specifying VirtualizationMode to Recycling then basic default virtualization. If you don’t specify VirtualizationMode then it will use default basic virtualization.

If you want to create your own Virtualization panel then you can use VirtualizingPanel class available in WPF. But in this case you have to write your own custom logic for creating and maintaining items inside your panel and also need to write logic to remove item once it goes out of scope.

<ListBox Name="ListBoxWithVirtualization" Height="100" Margin="5"
         VirtualizingStackPanel.IsVirtualizing="True"
         VirtualizingStackPanel.VirtualizationMode="Recycling" />


for (int i = 0; i < 1000000; i++)
    ListBoxWithVirtualization.Items.Add("Item - " + i.ToString());

As per above example, you can measure performance when items are loading into Listbox and after loading check scrolling performance of Listbox items as well. Now set IsVirtualizing property to false and measure the same. You will get better performance when IsVirtualizing property set to True.

Tuesday, May 3, 2011

Immutable types in DotNet


What are immutable types?

You can say class is immutable if you cannot change the value of its instances once assigned.

Most of the people know ‘string’ is immutable type when you change or modify value of string it will create new string object. It is recommended to use StringBuilder class instead of string if you want to change/modify string value frequently. But this is not the only immutable type available in dotnet there are many other immutable types also available in dotnet.

Delegates are also immutable types when you assign any function to delegate using += sign it will create new object internally. Anonymous type is also one of the example of immutable type when you create anonymous types you can not change value of its member. You can also create your own immutable types in C#. To create custom immutable type you can use const and read-only keyword in C#

Create immutable types in C#

    public class MyImmutableType
    {
        public const string Name = "Mitesh";
        public readonly int Age;
        public MyImmutableType(int age)
        {
            Age = age;
        }
    }

As per above example, you can assign Age property only once when you create an instance of MyImmutableType class. Once instance is created you can't change the value of Age property.

Create immutable types using Anonymous Types in C#

var myType = new { Name = "Mitesh", Age = 29 };
      myType.Age = 58 //Compiler error

By default anonymous types are immutable so you cannot change the value of any members of anonymous type.

Benefits of immutable types

Immutable types can be used in multi threading programming where multiple threads trying to access same data. The same time it is difficult to manage write and read access of it. You can use immutable types in such scenarios. One more place where you can use immutable type is to create Hashtable Keys. In common scenario where you want your data to be persisted once assigned but not want to modify or change in this case you can also go for immutable types.

Monday, May 2, 2011

DotNet 4.0 - New Features introduced in XAML 2009



New XAML with WPF 4.0 called XAML 2009. In XAML 2009, Microsoft added lots of new features but unfortunately this features not supported by Visual Studio 2010. If you want to use new features of XAML 2009, you have to use loose XAML file or uncompiled XAML file. You can dynamically load loose XAML content in window and use all the new features available in XAML 2009. In below examples i have used loose XAML content.

I am going to explain new features introduced in XAML 2009 here.

  • References
  • Built in Types
  • Generic Support
  • Advance Object Creation
  • Instance via Factory Methods
  • Arbitrary Dictionary Key

References

You can create references to the other element. Use x:Reference markup extension on Target property of Label to give reference of other element.

<StackPanel Orientation='Horizontal'>
<Label Target='{x:Reference NameTextBox}' >Enter _Name :</Label>
       <TextBox x:Name='NameTextBox' Width='150' > </TextBox>
</StackPanel>

As per above example, When user press ALT +N key the NameTextBox will get focus on it.

Built in Types

With XAML 2009, we can access commonly used type using ‘x’ namespace. It includes String, Int32, Int64, Decimal, Single, Array etc.

<x:String>WPF</x:String>

Generic Support

You can use generic collection in XAML. If you want to use ObservableCollection<T> in your XAML you can create it like this in XAML. You can use x:TypeArguments to specify Generic Type.

<ObservableCollection x:Key='collection' x:TypeArguments='local:Employee'
  xmlns='clr-namespace:System.Collections.ObjectModel;assembly=System'>
    <local:Employee>
        <x:Arguments>
            <x:String>Mitesh</x:String>
            <x:Int32>29</x:Int32>
        </x:Arguments>
    </local:Employee>
    <local:Employee>
        <x:Arguments>
            <x:String>Pritesh</x:String>
            <x:Int32>30</x:Int32>
         </x:Arguments>
    </local:Employee>
</ObservableCollection>

Similar way you can use generic list (e.g. List<string>) also.

Advance Object Creation

You can create an instance without non default constructors. You can specify one or more arguments to constructor by using x:Arguments.

XMAL:
<local:Employee>
<x:Arguments>
              <x:String>Mitesh</x:String>
              <x:Int32>29</x:Int32>
       </x:Arguments>
</local:Employee>
Code:
 public class Employee
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public Employee(string name, int age)
        {
            Name = name;
            Age = age;
        }
    }

Instance via Factory Methods

You can create an instance using Factory Methods in XAML. Using x:FactoryMethod you can specify any public static method and get an instance of your type. You can also use x:Arguments to pass parameters to static method.

<sys:Guid x:FactoryMethod='NewGuid' />

This is similar to call Guid id =Guid.NewGuid() in codebehind. As per above example, You can access NewGuid static method in XAML.

Arbitrary Dictionary Key

You can use x:Key as an object in XAML 2009.  In earlier version of XAML you can add x:Key as an attribute but with XAML 2009 you can add x:Key as an object.

<sys:Guid x:FactoryMethod='NewGuid'>
<x:Key>Uid</x:Key>
</sys:Guid>



Read more this here