Friday, April 29, 2011

Logical vs Visual Tree in WPF


Logical Tree
The logical representation of UI controls is called as Logical Tree. Logical Tree structure represents the hierarchy of UI controls and elements in WPF. Logical Tree doesn’t include inner controls of UI element. For example, Window contains StackPanel and StackPanel contains Buttons the Logical Tree can be represented as below
Visual Tree
The Logical representation of UI controls with its internal controls is called as Visual Tree. Visual Tree contains same elements the Logical Tree contains but it also contains elements or controls which are internally used to create the element or control in Logical Tree. In short, you can say Visual Tree contains all the elements the Logical Tree has with its template of each element. Please have a look on Visual Tree of above created Logical Tree.



Wednesday, April 27, 2011

Garbage Collector in Dotnet


Friends, In this article I am going to explain about Garbage Collector and its internal work. 

What is Garbage Collector?
Garbage collector is maintained by CLR in Dotnet. Garbage collector checks for the objects are not being used by the application inside managed heap. If it finds any such objects then it removes those objects from the memory. So during development developer doesn’t need to worry about it.

How memory gets allocated in managed heap?
When process starts, the runtime reserves a contiguous memory for it and this is called as managed heap. When application creates an object it will get allocated to the managed heap. GC internally divides objects in to two categories Small and Large. When CLR loaded initially two heap segments are allocated to it Small Object Heap(SOH) and Large Object Heap(LOH). When object creation request comes, at that time GC will check if the size of object is <= 85KB then it will get allocated on SOH and the objects are larger than 85KB will get allocated to the LOH.

What is Small Object Heap (SOH)?
CLR garbage collector is generational collector. Generations are logical view of GC. It has three generations Generation 0, Generation 1 and Generation 2. Generations only applies to SOH. Each generation maintain its memory threshold. By default all the objects having size <=85KB will get allocated to Gen 0.

What are the generations in GC and how they work internally?
When object allocation on Gen 0 reaches to its max limit the GC will start collecting data on this generation. The objects are not being used will get removed from memory and survived objects moved to the Gen 1. GC resets threshold level of Gen 0. Once Gen 0 collection completed GC start collecting data from Gen 1. Similar to Gen 0, GC collects and remove objects are not being used from memory during Gen 1 collection and survived objects moved to Gen 2. GC also resets threshold level of Gen 1. Objects in Gen 0 called as short lived objects and in Gen 2 called as long lived objects.

When Garbage Collector collects data?
GC automatically starts collecting data
1. When the allocation of objects in Generation 0 exceeds its max threshold limit. This is the most common scenario when garbage collector triggers and collects the data.
2. When system is running under low memory and user explicitly calls GC.Collect method.

What is Large Object Heap (LOH)?
LOH will get collected by GC when user explicitly calls GC.Collect method by passing GC.MaxGeneration as an argument. It also gets collected after completion of Gen 2 collection. While collecting data on LOH, if GC found objects are not being used will get removed from memory and marked as an empty so new object will get allocated in this available memory if the object size fits in available memory. The objects in this LOH will not get rearranged or compacted like Gen 0 and Gen 1 because all the objects are large and moving those objects is more expensive task.

Checkout below links to read more about this

Saturday, April 23, 2011

How to use BackgroundWorker to update UI in WPF


In this article I explained BackgroundWorker functionality using simple example. In this example I am adding millions of number in background to the Listbox. During this addition UI will be responsive and user can do some other work. When update complete it will notify user about the same.

BackgroundWorker in WPF

BackgroundWorker automatically perform task in separate thread and provide a notification to UI Thread when necessary. If you have long running task in your application you should consider putting this in separate background thread so that your UI remains responsive.

Whatever work you want to perform in background you can add it into DoWork event of BackgroundWorker. It has RunWorkerCompleted event too which fires when BackgroundWorker completes its task. So you can write some code in this event to notify user about completion of BackgroundWorker thread. To Start BackgroundWorker, use RunWorkerAsync method. When you call this method it will start executing code written in DoWork event.

XAML

<Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="0.1*"/>
            <RowDefinition />
            <RowDefinition Height="0.2*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="100"/>
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <TextBlock Grid.Row="0" Grid.Column="0" Margin="5"
                   HorizontalAlignment="Right" Text="List of Numbers:" />
        <TextBlock Grid.Row="1" Grid.Column="0" Margin="5" Height="25"
                   HorizontalAlignment="Right" Text="" Name="Status"
                   Background="Yellow" VerticalAlignment="Top"/>
        <ListBox Grid.Row="0" Grid.Column="1" Name="NumbersList"
                 Grid.RowSpan="2"/>
        <Button Grid.Row="2" Grid.ColumnSpan="2" Height="30"
                Width="125" Content="Fill ListBox"
                Name="FillListBox" Click="FillListBox_Click" />
</Grid>

Code
        BackgroundWorker workerThread;
        public BackgroundWorkerSample()
        {
            InitializeComponent();
            workerThread = new BackgroundWorker();
            workerThread.DoWork += new DoWorkEventHandler(workerThread_DoWork);
            workerThread.RunWorkerCompleted += new
                RunWorkerCompletedEventHandler(workerThread_RunWorkerCompleted);
        }

        private void workerThread_RunWorkerCompleted(object sender,                                                              RunWorkerCompletedEventArgs e)
        {
            Status.Text = "Completed";
            FillListBox.IsEnabled = true;
        }

        private void workerThread_DoWork(object sender, DoWorkEventArgs e)
        {
            Action<int> workMethod = (i) => NumbersList.Items.Add("Number: " + i);
            for (int i = 0; i < 1000000; i++)
                NumbersList.Dispatcher.BeginInvoke(DispatcherPriority.Background, 
                workMethod, i);
        }

        private void FillListBox_Click(object sender, RoutedEventArgs e)
        {
            workerThread.RunWorkerAsync();
            FillListBox.IsEnabled = false;
            Status.Text = "Loading...";
        }







Friday, April 22, 2011

How to use WPF GridSplitter inside Grid


In this article I am going to demonstrate how to use GridSplitter inside Grid using simple example.


Gridsplitter provides facility to change width of columns and height of rows at runtime to the users. You can add GridSplitter control similar to other controls inside Grid. You can add GridSplitter control with existing content but the best approach to add it in separate row or column. You should remember that GridSplitter resize entire column or row not only single cell. You can use ColumnSpan or RowSpan to achieve this. You can also specify Horizontal/Vertical alignment to stretch GridSplitter across column or row. GridSplitter can be declared in nested Grid. You can change width or height of GridSplitter to make it more visible.

You can set ShowsPreview property to True if you don’t want to resize your column or row on mouse move during dragging. You can see shadow while resizing column or row if this property set to true. By default value of this property is set to false. You can also set DragIncrement property if you want to resize some fix amount of change on drag.

<Grid Width="250" Height="150" VerticalAlignment="Top">
        <Grid.RowDefinitions>
            <RowDefinition Height="20" />
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="20"/>
            <RowDefinition Height="40"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="90"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <TextBlock Grid.Row ="0" Grid.Column="0" Text="Name:"
                   HorizontalAlignment="Right" />
        <TextBox Grid.Row ="0" Grid.Column="2"/>
        <GridSplitter Grid.Column="1" Grid.RowSpan="3" Width="2"
                      ShowsPreview="False" DragIncrement="10"
                      HorizontalAlignment="Stretch"
                      VerticalAlignment="Stretch" />
        <GridSplitter Grid.Row="1" Grid.ColumnSpan="3" Height="2"
                      ShowsPreview="False" DragIncrement="20"
                      HorizontalAlignment="Stretch"
                      VerticalAlignment="Stretch" />
        <TextBlock Grid.Row ="2" Grid.Column="0" Text="City:"
                   HorizontalAlignment="Right" />
        <TextBox Grid.Row ="2" Grid.Column="2"/>
        <Button Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="3"
                Content="Click Me!" Height="25" Width="100" 
                Margin="0,10,0,0"
                HorizontalAlignment="Center" VerticalAlignment="Top"/>
</Grid>


Layout panels in WPF


Friends, This is my First Article. Finally I convinced myself to start writing articles. Please give your comments and encourage me to write more articles. Thanks in Advance.

I am going to introduce and explain some basics of Layout panels available in WPF in this article.

Layout panels in WPF

  • StackPanel
  • WrapPanel
  • DockPanel
  • Grid
  • UniformGrid
  • Canvas

StackPanel – Places elements either horizontally or vertically in a stake. You can change orientation of elements inside StackPanel to either horizontally or vertically by setting Orientation property. By default StackPanel places elements vertically.



WrapPanel – Places elements inside WrapPanel horizontally or vertically like StackPanel but in WrapPanel all elements are wrapped by default. You can change orientation of elements either horizontally or vertically by setting Orientation property same as StackPanel. By default WrapPanel places elements horizontally.



DockPanel – Aligns elements to the edge of the container. You can place elements to TOP, BOTTOM, LEFT and RIGHT edge of the container by setting DockPanel.Dock attached property on element.  You can also fill element in remaining space by setting LastChildFiled property to True of DockPanel.



Grid – Places elements in row and column format similar to table. This is the most powerful layout control in WPF. You can create grid rows and columns by filling Grid.ColumnDefinitions and Grid.RowDefinitions. You can use Grid.Row and Grid.Column attached properties to place elements inside cells. You can also use Grid.RowSpan and Grid.ColumnSpan attached properties to span columns and rows. You can set ShowGridLines property to True to display gridlines in Grid.




UniformGrid - Places elements in row and column format uniformly. UniformGrid is limited version of Grid where all rows and column size are same. Each cell contains only single control. Elements are places in UniformGrid in the order they are declared. By default it uses LeftToRight flow direction and you can change flow direction setting FlowDirection property of UniformGrid. This grid mostly used to layout elements quickly.


Canvas – Places elements using exact coordinates. You can place an element on Canvas by setting Canvas.Left, Canvas.Top, Canvas.Right and Canvas.Bottom attached properties on element.