Wednesday, May 27, 2009

Microsoft Azure, Bull Dog, Zurich ???

Someone mentioned “Zurich” and I was again wondering how it was different from “Geneva” or “Zermatt”.

Finally searching got me into this very useful “codename” info.

And I thought only “open-source” can think of funny names.

Hope you will find it useful.

Hats off to Mary Jo Foley for compiling this… here is the list.

Technorati Tags: ,,

Monday, May 18, 2009

Empty Data template in Silverlight DataGrid

One of my colleagues mentioned the “missing feature” of silverlight datagrid where in a message needs to be displayed when no records are present in the datagrid Itemsource.

So the objective is to make a datagrid which have a Empty Data grid template which may be overridden in case there are no records in the datagrid Item source. Like below.

image

The datagrid itself is trivial. I have introduced 3 dependency properties and overridden the Datagrid and the DataTemplate itself.

Here is how the XAML looks like

 

   1: <local:DataGridWithEmptyTemplate ItemsSource="{Binding Person}"  x:Name="MyDataGrid" AutoGenerateColumns="True">



   2:            <local:DataGridWithEmptyTemplate.EmptyTemplate>



   3:                <local:EmptyDataTemplate Width="420.0" EmptyHeaderText="FirstName    |   LastName    |   Gender    " >



   4:                    <Border CornerRadius="5" BorderThickness="2" BorderBrush="Gray" Margin="5" >



   5:                        <Border.Background>



   6:                            <LinearGradientBrush EndPoint="0.512,1.154" StartPoint="0.512,0.154">



   7:                                <GradientStop Color="Red" Offset="1"/>



   8:                                <GradientStop Color="AntiqueWhite" Offset="0.339"/>



   9:                            </LinearGradientBrush>



  10:                        </Border.Background>



  11:                        <StackPanel Width="Auto" Background="Transparent">



  12:                            <TextBlock Text="No Records"  ></TextBlock>



  13:                            <TextBlock Text="Please change the criteria. This template may be changed using XAML!!"></TextBlock>



  14:                        </StackPanel>



  15:                    </Border>



  16:                </local:EmptyDataTemplate>



  17:            </local:DataGridWithEmptyTemplate.EmptyTemplate>



  18:        </local:DataGridWithEmptyTemplate>




you may notice the Width and EmptyHeaderText Properties of EmptyDataTemplate.



The code behind looks like





   1: public class EmptyDataTemplate : DataTemplate



   2:    {



   3:        public EmptyDataTemplate()



   4:        {



   5:            



   6:        }



   7:  



   8:        public string EmptyHeaderText



   9:        {



  10:            get



  11:            {



  12:                return (string)GetValue(EmptyHeaderTextProperty);



  13:            }



  14:            set



  15:            {



  16:                SetValue(EmptyHeaderTextProperty, value);



  17:            }



  18:        }



  19:  



  20:        public static readonly DependencyProperty EmptyHeaderTextProperty = DependencyProperty.Register(



  21:            "EmptyHeaderText", typeof(string), typeof(EmptyDataTemplate), new PropertyMetadata(null));



  22:  



  23:        public double Width



  24:        {



  25:            get



  26:            {



  27:                return (double)GetValue(WidthProperty);



  28:            }



  29:            set



  30:            {



  31:                SetValue(WidthProperty, value);



  32:            }



  33:        }



  34:  



  35:        public static readonly DependencyProperty WidthProperty = DependencyProperty.Register(



  36:            "Width", typeof(double), typeof(EmptyDataTemplate), new PropertyMetadata(100.0,null));



  37:    }



  38:  



  39:    public class DataGridWithEmptyTemplate : DataGrid



  40:    {



  41:  



  42:        public static TextBlock textBlock = new TextBlock();



  43:  



  44:        public DataGridWithEmptyTemplate()



  45:        {



  46:  



  47:            this.Loaded += new RoutedEventHandler((o, e) =>



  48:            {



  49:                int count = 0;



  50:                base.ItemsSource = this.ItemsSource;



  51:                var q = (IEnumerable)base.ItemsSource;



  52:                if (q != null)



  53:                {



  54:                    foreach (var items in q)



  55:                    {



  56:                        count++;



  57:                    }



  58:                }



  59:                if (count == 0)



  60:                {



  61:                    EmptyDataTemplate nodeTemplate = (EmptyDataTemplate)this.EmptyTemplate;



  62:                    if (nodeTemplate != null)



  63:                    {



  64:                        DataGridTemplateColumn dataGridTemplateColumn = new DataGridTemplateColumn();



  65:                        



  66:                        dataGridTemplateColumn.CellTemplate = nodeTemplate;



  67:                        dataGridTemplateColumn.Header = nodeTemplate.EmptyHeaderText;



  68:                        dataGridTemplateColumn.Width = new DataGridLength(nodeTemplate.Width);



  69:                        // we can even display the properties of object binded. 



  70:                        //var properties = from propertyInfo in typeof(Person).GetProperties()



  71:                        //                 select propertyInfo.Name;



  72:                        //foreach (string header in properties)



  73:                        //{



  74:                        //    d.Header = d.Header + header + "  |  ";



  75:                        //}



  76:                        FrameworkElement frameworkElement = dataGridTemplateColumn.CellTemplate.LoadContent() as FrameworkElement;



  77:                        this.Columns.Add(dataGridTemplateColumn);



  78:                        base.ItemsSource = new List<UIElement>() { frameworkElement };



  79:                        base.AutoGenerateColumns = false;



  80:                    }



  81:                }



  82:            }



  83:            );



  84:        }



  85:  



  86:        public EmptyDataTemplate EmptyTemplate



  87:        {



  88:            get



  89:            {



  90:                return (EmptyDataTemplate)GetValue(EmptyTemplateProperty);



  91:            }



  92:            set



  93:            {



  94:                SetValue(EmptyTemplateProperty, value);



  95:            }



  96:        }



  97:  



  98:        public static readonly DependencyProperty EmptyTemplateProperty = DependencyProperty.Register(



  99:            "EmptyTemplate", typeof(EmptyDataTemplate), typeof(DataGridWithEmptyTemplate), new PropertyMetadata(null));



 100:  



 101:    }




So, even if you forget to assign Itemsource or assigned itemsource which have zero items like before



MyDataGrid.ItemsSource = null;/// or even if you forget to assign Itemsource



MyDataGrid.ItemsSource = new List<Person>();



The result is same as below. You may override the template too!!!





   1: <local:DataGridWithEmptyTemplate ItemsSource="{Binding Person}"  x:Name="MyDataGrid" AutoGenerateColumns="True">



   2:             <local:DataGridWithEmptyTemplate.EmptyTemplate>



   3:                 <local:EmptyDataTemplate Width="420.0" EmptyHeaderText="FirstName    |   LastName    |   Gender    " >



   4:                     <Border CornerRadius="5" BorderThickness="2" BorderBrush="Gray" Margin="5" >



   5:                         <Border.Background>



   6:                             <LinearGradientBrush EndPoint="0.512,1.154" StartPoint="0.512,0.154">



   7:                                 <GradientStop Color="White" Offset="1"/>



   8:                                 <GradientStop Color="AntiqueWhite" Offset="0.339"/>



   9:                             </LinearGradientBrush>



  10:                         </Border.Background>



  11:                         <StackPanel Width="Auto" Background="Transparent">



  12:                             <TextBlock Text="No Records" Foreground="Red" ></TextBlock>



  13:                             <TextBlock Text="This template may be changed using XAML!!" Foreground="Red"></TextBlock>



  14:                         </StackPanel>



  15:                     </Border>



  16:                 </local:EmptyDataTemplate>



  17:             </local:DataGridWithEmptyTemplate.EmptyTemplate>



  18:         </local:DataGridWithEmptyTemplate>




image



Needless to say, the other functionality of datagrid remain the same as we have only introduced new DPs which have NO impact on existing functionality.



Finally here is the code.



Technorati Tags: ,

Friday, May 08, 2009

Dependency Properties

Dependency properties is one concept which i always marvel. As programmer / developer i always like the concept, as by just introducing DP, so many stuff now is so easy(Read Template programming in XAML).

DP is called a BEAST (in Silverlight and WPF) for reasons of complexity involved in understanding them. Also, of course, because they are so powerful language paradigm. I sometimes do think DP did not actually got their due. I mean, so many efforts is gone into explaining Lambda expressions, LINQ, and other stuff but DP still remains a taboo.

So, when i took up to the task of explaining WPF, many were skeptical about my thought of actually introducing DP in second session itself. (the audiences had people from testing and not-so-much-into-coding). But i have always felt, new programming concept are like mathematics, once you have the concept, its interesting. But, mostly the concept part is ignored and then it all becomes a mystery.

here is a whirlwind introduction of DP… The ppts are here and the demo code here.

Below is explanations:

Purpose of dependency properties is to compute the value of a property based on values of other inputs available

 

DPs provide for

–Change Notification

–Callbacks

–Property value validation

–Property value inheritance *

–Participation in animations *

–Participation in Styles *

–Participation in Templates *

–Data binding

–Layout changes *

Overriding default data values *

Example 1 – Explaining DP visual inheritance

consider:

   1: <Window x:Class="Demo2.Window1"



   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"



   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" TextElement.FontSize="15"



   4:     Title="Window1" Height="300" Width="300">



   5:     <StackPanel>



   6:         <TextBlock Text="this has inherited Fonstsize DP property"></TextBlock>



   7:         <TextBlock Text="this has its own Fonstsize DP property" FontSize="20"></TextBlock>



   8:     </StackPanel>



   9: </Window>






output is : The one encircled in Red inherits Font size from visual parent Window, which sets TextElement.FontSize to 15. The one encircled in Blue overrides this to font size 20.



DP1



Example2: Now lets implement our own version of DP inheritance for POC. The idea is to introduce a new DP “Text” for stackpanel which is propagated to its visual children DP.



Consider:







   1: namespace Demo2



   2: {



   3:     /// <summary>



   4:     /// Interaction logic for Window2.xaml



   5:     /// </summary>



   6:     public partial class Window2 : Window



   7:     {



   8:         public Window2()



   9:         {



  10:             InitializeComponent();



  11:         }



  12:     }



  13:     public class MyStackPanel : StackPanel



  14:     {



  15:  



  16:  



  17:         public string Text



  18:         {



  19:             get { return (string)GetValue(TextProperty); }



  20:             set { SetValue(TextProperty, value); }



  21:         }



  22:  



  23:         // Using a DependencyProperty as the backing store for Text.  This enables animation, styling, binding, etc...



  24:         public static readonly DependencyProperty TextProperty =



  25:             DependencyProperty.Register("Text", typeof(string), typeof(MyStackPanel), 



  26:             new FrameworkPropertyMetadata("stackPanel Default Text",



  27:                 FrameworkPropertyMetadataOptions.Inherits));



  28:  



  29:     }



  30:  



  31:  



  32:     public class MyButton : Button 



  33:     {



  34:         public string Text



  35:         {



  36:             get { return (string)GetValue(TextProperty); }



  37:             set { SetValue(TextProperty, value); }



  38:         }



  39:  



  40:         // Using a DependencyProperty as the backing store for Text.  This enables animation, styling, binding, etc...



  41:         public static readonly DependencyProperty TextProperty =



  42:             MyStackPanel.TextProperty.AddOwner(typeof(MyButton), 



  43:             new FrameworkPropertyMetadata("Button Default Text", FrameworkPropertyMetadataOptions.Inherits));



  44:     }



  45: }




We have added DP for both StackPanel and button. However in Button the DP is registered as



public static readonly DependencyProperty TextProperty =

            MyStackPanel.TextProperty.AddOwner(typeof(MyButton),


            new FrameworkPropertyMetadata("Button Default Text", FrameworkPropertyMetadataOptions.Inherits));



now here are scenarios:



1. if we set Text DP for both MyStackPanel and MyButton as below





   1: <StackPanel>



   2:         <local:MyStackPanel x:Name="sp" Text="This is Test set by StackPanel">



   3:             <ContentPresenter Content="{Binding ElementName=sp, Path=Text}" ></ContentPresenter>



   4:             <local:MyButton Text="This is text set by MyButton"



   5:                 Content="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=Text}"                           



   6:                             ></local:MyButton>



   7:         </local:MyStackPanel>



   8:     </StackPanel>




output is



image 



2. if we set ONLY the Text in MYstackpanel, the MYButton Text will inherit from visual parent as below





   1: <local:MyStackPanel x:Name="sp" Text="This is Test set by StackPanel">



   2:             <ContentPresenter Content="{Binding ElementName=sp, Path=Text}" ></ContentPresenter>



   3:             <local:MyButton 



   4:                 Content="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=Text}"                           



   5:                             ></local:MyButton>



   6:         </local:MyStackPanel>










image Notice button caption is same as Stackpanel



3. If we Do NOT set any text, the TEXT will assume default values for BOTH.



image 



4. If we only set Button Text DP





   1: <local:MyStackPanel x:Name="sp" >



   2:            <ContentPresenter Content="{Binding ElementName=sp, Path=Text}" ></ContentPresenter>



   3:            <local:MyButton Text="This is text set by MyButton"



   4:                Content="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=Text}"                           



   5:                            ></local:MyButton>



   6:        </local:MyStackPanel>



image



Notice in above case the Text DP is still default for stackpanel. that is DP is NOT propogated to visual parent from child.



We want to achieve the above case we have to make Attached DP property. I which parent property may be changed by the child element contained in parent



Attached DP Property



for this we will override an stackpanel and expose a Attached DP text which may be set by ANY visual children.





   1: <StackPanel>



   2:        <local:MyStackAttached x:Name="sp">



   3:            <Button x:Name="btn" local:MyStackAttached.Text="This text set by child button" Content="OK"></Button>



   4:        </local:MyStackAttached>



   5:        <TextBox x:Name="textBox" ></TextBox>



   6:    </StackPanel>








   1: namespace Demo2



   2: {



   3:     /// <summary>



   4:     /// Interaction logic for Window3.xaml



   5:     /// </summary>



   6:     public partial class Window3 : Window



   7:     {



   8:         public Window3()



   9:         {



  10:             InitializeComponent();



  11:             // notice , we are getting DP value from btn and NOT stackpanel :D



  12:             textBox.Text =  (string)btn.GetValue(MyStackAttached.TextProperty);



  13:         }



  14:     }



  15:  



  16:     public class MyStackAttached : StackPanel



  17:     {



  18:         static ContentPresenter contentPresenter = new ContentPresenter() { Height = 100.0, Width = 200.0 };



  19:  



  20:         public MyStackAttached()



  21:         {



  22:             base.Children.Add(contentPresenter);



  23:         }



  24:  



  25:         public static string GetText(DependencyObject obj)



  26:         {



  27:             return (string)obj.GetValue(TextProperty);



  28:         }



  29:  



  30:         public static void SetText(DependencyObject obj, string value)



  31:         {



  32:             obj.SetValue(TextProperty, value);



  33:         }



  34:  



  35:         // Using a DependencyProperty as the backing store for Text.  This enables animation, styling, binding, etc...



  36:         public static readonly DependencyProperty TextProperty =



  37:             DependencyProperty.RegisterAttached("Text", typeof(string), typeof(MyStackAttached),



  38:             new UIPropertyMetadata((o, e) =>



  39:             {



  40:                 contentPresenter.Content = GetText(o); 



  41:             }



  42:             ));



  43:     }



  44: }




output:



image



Data Validation, Coerce using DP



The idea is to create a textbox which accepts only correct AGE values between 1 and 100. This is achieved by exposing a DP AGE.





   1: public class MyTextBox : TextBox



   2:    {



   3:        public int Age



   4:        {



   5:            get { return (int)GetValue(AgeProperty); }



   6:            set { SetValue(AgeProperty, value); }



   7:        }



   8:  



   9:        // Using a DependencyProperty as the backing store for Age.  This enables animation, styling, binding, etc...



  10:        public static readonly DependencyProperty AgeProperty =



  11:            DependencyProperty.Register("Age", typeof(int), typeof(MyTextBox), new FrameworkPropertyMetadata(1,



  12:            FrameworkPropertyMetadataOptions.None, new PropertyChangedCallback((o, e) => { }), new CoerceValueCallback((o, e) =>



  13:            {



  14:                int current = (int)e;



  15:                if (current <=0 )



  16:                    current = 1;



  17:                return current;



  18:            })),



  19:             new ValidateValueCallback((o) =>



  20:             {



  21:                 int current = (int)o;



  22:                 if (current > 100)



  23:                 { return false; }



  24:                 else



  25:                 { return true; }



  26:             }));



  27:    }



the XAML looks like:











   1: <StackPanel>



   2:         <TextBox x:Name="mytext"></TextBox>



   3:         <local:MyTextBox Age="{Binding ElementName=mytext, Path=Text, Mode=TwoWay}"



   4:                         Text="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=Age, Mode=TwoWay}" 



   5:                          ></local:MyTextBox>



   6:     </StackPanel>






Output:



imageWhen Age value is <= 0 , the Age=1



image When age is valid



image  when age > 100 then Age =1



 



Along with above i have also included a unit test case for the last scenario in the code.



Your thoughts / comments are welcome:



Technorati Tags: ,,,