Sunday, 3 March 2013

Part 3: Binding ListBox to XML

This post is the third in the series of ListBox control. Here is the reference of all the post in this series for quick reference.

Part - 1: ListBox basics - Adding Items manually to ListBox and understanding properties of ListBox

Part - 2: Data Binding in ListBox (Binding ListBox to data source)

Part - 3: Binding ListBox to XML

Part - 4: Applying style to ListBox

Part - 5: Applying style to ListBox, Continued

Part - 6: ListBox custom ControlTemplate

 

Part 3: Binding ListBox to XML

WPF provides very handy control “XmlDataProvider” that can be used to load XML from variety of sources (i.e provides xml data in XAML, separate XML file or set the XMLDocument programmatically).

In XAML below, we added XmlDataProvider to windows resources and provided xml data in XAML.

<XmlDataProvider x:Key="FruitsXML">
<x:XData>
<Fruits>
<Fruit Name="Apple">
<ImagePath>Images\\Apple.png</ImagePath>
<Calories>61</Calories>
<Vitamins>A,C</Vitamins>
</Fruit>
<Fruit Name="Orange">
<ImagePath>Images\\Orange.png</ImagePath>
<Calories>51</Calories>
<Vitamins>A,B1,C</Vitamins>
</Fruit>
</Fruits>
</x:XData>
</XmlDataProvider>


Binding ListBox to XmlDataProvider

<ListBox Name="lstFruits" ItemsSource="{Binding Source={StaticResource ResourceKey=FruitsXML}, XPath=Fruits/Fruit}" DisplayMemberPath="@Name" SelectedValuePath="ImagePath"></ListBox>


There are 4 important parts in binding:



Binding Source is FruitsXML which is a XmlDataProvider static resource defined in windows resources section.


XPath: Source is set to entire xml data. Hence we set XPath to “Fruits/Fruit” which binds ListBox to all Fruit elements.


DisplayMemberPath: Each item in ListBox is bound an instance of Fruit element from XML, so we need to choose which child element/attribute of Fruit element to display. We choose to display Name attribute. “@” symbol is used to indicate attribute.


SelectedValuePath: SelectedValuePath is set to “ImagePath” element of Fruit. Hence when we access “SelectedValue” property in code, it will return ImagePath of selected item.


Using XML File instead of static XML data


XmlDataProvider has Source property which can be used to specify path of XML file to load data. We can move XML data provided in XAML to separate XML file and then specify Source property of XmlDataProvider XML file. Remaining code would be same for binding ListBox.

Part - 2: Data Binding in ListBox

This post is the second in the series of ListBox control. In previous post, we learned some basic of ListBox control, adding items manually to ListBox control in XAML and code behind, and examining some properties of ListBox control.

Here is the reference of all the post in this series for quick reference.

Part - 1: ListBox basics - Adding Items manually to ListBox and understanding properties of ListBox

Part - 2: Data Binding in ListBox (Binding ListBox to data source)

Part - 3: Binding ListBox to XML

Part - 4: Applying style to ListBox

Part - 5: Applying style to ListBox, Continued

Part - 6: ListBox custom ControlTemplate

 

Part - 2: Data Binding in ListBox

In last post we learnt how to add static items to ListBox in XAML and code. But Most of the times we need to populate ListBox control by binding the control to some data source, instead of adding items manually. Data source can be xml, business object, DataTable and some other type that contains data.

Binding ListBox to Custom Business Object

Let’s create a simple class “Fruit” to hold fruit information.

public class Fruit
{
public string Name { get; set; }
public string ImagePath { get; set; }
public Int32 Calories { get; set; }
public string Vitamins { get; set; }
}


Add simple ListBox control to XAML

<ListBox Name="lstFruits"></ListBox>


In code behind (constructor), Create a list of Fruits and bind to ListBox control.

List<Fruit> myFruits = new List<Fruit>()
{
new Fruit() { Name = "Apple", ImagePath = "Images\\Apple.png", Calories = 61, Vitamins = "A,C" },
new Fruit() { Name = "Orange", ImagePath = "Images\\Orange.png", Calories = 51, Vitamins = "A,B1,C" },
new Fruit() { Name = "Grape", ImagePath = "Images\\Grapes.png", Calories = 40, Vitamins = "C" },
new Fruit() { Name = "Mango", ImagePath = "Images\\Mango.png", Calories = 80, Vitamins = "A,B1,C" }
};

lstFruits.ItemsSource = myFruits;


ItemSource property can be bound to any data source that implements IEnumerable. Generic List is one of them that implements IEnumerable.


Output:



In above image, it is visible that ListBox control is correctly bound to the data source as it shows 4 items in the list. Each item in ListBox is bound to an instance of Fruit class. As we have not specified any property of Fruit class, by default ToString() method of Fruit object is called which returns “ListboxSample.Fruit” value. i.e <Namespace.ClassName>


Modify XAML to bind to Name property by adding DisplayMemberPath

<ListBox Name="lstFruits" DisplayMemberPath="Name"></ListBox>

and here is the output



Now we examine the properties as we did in post 1.



One noticeable difference is that “SelectedItem” and “SelectedValue” property returns type “ListBoxSample.Fruit” instead of “ListBox.ListBoxItem” as each item is bound to instance of Fruit class. So to access properties we type cast to Fruit class.


Now let’s add one more property “SelectedValuePath”.

<ListBox Name="lstFruits" DisplayMemberPath="Name" SelectedValuePath="ImagePath"></ListBox>

Examine the difference.



lstFruits.SelectedValue now directly returns value of “ImagePath” property from Fruit class instead of an instance of Fruit class. Many times its quite useful to bind “SelectedValuePath” property to Unique Identifier (ID) of class so we can directly get Unique Identifier of selected item.


Some more fun with ListBox DataBinding.


Add Image control below ListBox control. Bind Image control Source property to SelectedValue property of ListBox control. This is called Element to Element binding.

<Image Grid.Row="1" Source="{Binding ElementName=lstFruits, Path=SelectedValue}" Stretch="Uniform"></Image>


Run the application and select items in ListBox.



As we have specified SelectedValuePath property of ListBox to ImagePath property of Fruit class, when any item is selected in ListBox control, SelectedValue property  of ListBox will return ImagePath of selected fruit item. Now we have bound Source property of Image control to SelectedValue property of ListBox control which would return ImagePath. Hence selecting fruit in ListBox will show image below.


ListBox also provides an alternative way of achieving same result.


IsSynchronizedWithCurrentItem


When ListBox control is bound to Data Source, internally an instance of ICollectionView is created depending on the type of of Data Source and then this view is bound to ListBox. If IsSynchronizedWithCurrentItem of ListBox is set to True, when user select any item in ListBox control, same item is set as current item in underlying view. This way if any other control (in our case Image control) is bound to any property of same data source, then it would reflect value from currently selected item in ListBox.


Let’s see what it means?


First of all we need to bind both ListBox control and Image control to same data source. Here DataContext property becomes more useful. DataContext property is present in every control and can be set to any data source. When DataContext is set in parent control, all child controls can inherit that data source from parent control. Hence we set DataContext property of entire Window.

List<Fruit> myFruits = new List<Fruit>()
{
new Fruit() { Name = "Apple", ImagePath = "Images\\Apple.png", Calories = 61, Vitamins = "A,C" },
new Fruit() { Name = "Orange", ImagePath = "Images\\Orange.png", Calories = 51, Vitamins = "A,B1,C" },
new Fruit() { Name = "Grape", ImagePath = "Images\\Grapes.png", Calories = 40, Vitamins = "C" },
new Fruit() { Name = "Mango", ImagePath = "Images\\Mango.png", Calories = 80, Vitamins = "A,B1,C" }
};

this.DataContext = myFruits;


DataContext of entire window is set to list of fruits. Hence ListBox control and Image control in Window would inherit data source from Window.

<ListBox Name="lstFruits" ItemsSource="{Binding}" DisplayMemberPath="Name" SelectedValuePath="ImagePath" IsSynchronizedWithCurrentItem="True"></ListBox>

<Image Grid.Row="1" Stretch="Uniform" Source="{Binding ImagePath}"></Image>


As ListBox inherits data source from parent, ItemSource for ListBox is set to empty Binding. IsSynchronizedWithCurrentItem = True will make sure that any item selected in ListBox will be the current item in ICollectionView.


Image control is bound to ImagePath property of Fruit class. hmm, that sounds interesting. how come any ContentControl like Image control can be bound to collection. That’s beauty of WPF DataBinding. When any property of ContentControl is bound to a property in list, current item (by default first item) in the list will be used for binding.


Now run the application and see the action.




When application is run, by default first item is the current item in ICollectionView. Hence “Apple” is selected in ListBox and Apple is displayed in Image control.


Now as we change the selection in ListBox, current item in ICollectionView is updated and hence image gets displayed for selected item.



This is very handy feature and useful in different scenarios.


I hope this would provide you a good insight into DataBinding.

Part - 1: ListBox basics

In this series of ListBox control, we would cover basics to advanced usage of ListBox control.

Part - 1: ListBox basics - Adding Items manually to ListBox and understanding properties of ListBox

Part - 2: Data Binding in ListBox (Binding ListBox to data source)

Part - 3: Binding ListBox to XML

Part - 4: Applying style to ListBox

Part - 5: Applying style to ListBox, Continued

Part - 6: ListBox custom ControlTemplate

 

Part - 1: ListBox Basics

ListBox control in WPF falls in category of Items Controls and used to to display list of related items. Below is the basic syntax of ListBox control.

<ListBox Name="lstFruits">
<ListBoxItem Content="Apple"></ListBoxItem>
<ListBoxItem Content="Oranges"></ListBoxItem>
<ListBoxItem Content="Mango"></ListBoxItem>
<ListBoxItem Content="Grapes"></ListBoxItem>
<ListBoxItem Content="Banana"></ListBoxItem>
</ListBox>


In above code, ListBox is a control and contains list of ListBoxItem. ListBoxItem is a specialized type of ContentControl for ListBox control. Run the application to see your ListBox in action.


Output:



To examine the properties of ListBox control, I have added Button control, handled click event of control, put the breakpoint in button click event in code, added multiple properties to watch in watch window, run the application, select “Oranges” item, breakpoint is hit and here is what I see in my properties watch window.



Tip: QuickWatch window can be used to quickly examine  value of any property at runtime. Watch window can be to add multiple properties to watch and examine their properties when they are available.


Watch window has 3 columns. Name is name of the property to watch. Value is the current value in that property. Type is the type of the value that property returns.



1. lstFruits.Items.Count = 5 = number of items in ListBox control.


2. lstFruits.SelectedIndex = 1 = As we have selected Oranges. Note: Index starts by 0.


3. lstFruits.SelectedItem: This is interesting. We would expect “Oranges” string. But if we look at the Type returned by this property, it is object and not string. As we have added ListBoxItem in ListBox, it is returning object of type ListBoxItem corresponding to “Oranges”. We can get “Oranges” text by using Content property as ListBoxItem is a ContentControl and every ContentControl has Content property. Check 4th point for the syntax.


4. ((ListBoxItem)lstFruits.SelectedItem).Content: lstFruits.SelectedItem will return object. Hence we need to type cast to “ListBoxItem” and then we can access “Content” property which would be our “Oranges” string.


5. lstFruits.SelectedValue: This is same as SelectedItem property. In this case, both are some value but we can provide different values for both, which we would cover when we DataBind to custom objects.


6. lstFruits.SelectedItems: returns collection of items that are selected in ListBox. Type column shows type returned by this property which is “SelectedItemCollection”.  Value shows says “Count = 1”, because Count is the default property when no property is specified. We can enumerate this collection to get individual selected items.


Syntax for enumeration:

foreach (ListBoxItem item in lstFruits.SelectedItems)
{

}

By default, “SelectionMode” property of ListBox control is set to “Single”. Below are the possible values for “SelectionMode” property.


SelectionMode:


Single (Default): Single means only one value can be selected.
Multiple: Multiple means multiple values can be selected.
Extended. Extended allows selection of multiple values in combination with CTRL or SHIFT key. Use CTRL key to select/de-select individual random items and SHIFT key to select consecutive items.


SelectedItems property is more meaningful when SelectionMode is set to Multiple or Extended. In this case we can select multiple items in ListBox control and access those selected items using SelectedItems property.


7. lstFruits.Items: returns collection of all items in ListBox control. This is useful when we want to enumerate all items or we want to perform other possible operations on collection.


I hope this would provide a good insight into some useful properties of ListBox control.


In ListBox control above we added ListBoxItem, but ListBox is not just restricted to ListBoxItem, it can contain any ContentControl as items. See below image for different types of ContentControl added.



Note: I have made 2 changes:



Replaced ListBoxItem with CheckBox



Added HorizontalContentAlignment = “Stretch”. So that all CheckBox controls occupies entire horizontal space in ListBox control.


Now run the application.



We select 3 items “Oranges”, “Grapes” and “Banana”. So SelectionMode property of ListBox control (“Single”) does not affect because we are not selecting items but we are using CheckBox to check/select them. As we are not selecting the items, hence all properties we examined above for selection would not be useful. Let examine the Watch.



Interesting, so how do I get the checked items. Simple loop through the items, type case each item to CheckBox and use Checked property.

private void Button_Click(object sender, RoutedEventArgs e)
{
List<string> selectedItems = new List<string>();
foreach (CheckBox chkCurrentItem in lstFruits.Items)
{
if (chkCurrentItem.IsChecked.Value)
{
selectedItems.Add(chkCurrentItem.Content.ToString());
}
}
}


It is also possible to add combination of items in ListBox control. See below image. Any control derived from ContentControl can be added as individual item to ListBox.



Dynamically adding items to ListBox in Code

lstFruits.Items.Add("Apple");
lstFruits.Items.Add("Oranges");
lstFruits.Items.Add("Mango");
lstFruits.Items.Add("Grapes");
lstFruits.Items.Add("Banana");


Above code will add 5 items to ListBox and each item would be implicitly converted to ListBoxItem.

lstFruits.Items.Add(new CheckBox() { Content = "Apple" });
lstFruits.Items.Add(new CheckBox() { Content = "Oranges" });
lstFruits.Items.Add(new CheckBox() { Content = "Mango" });
lstFruits.Items.Add(new CheckBox() { Content = "Grapes" });
lstFruits.Items.Add(new CheckBox() { Content = "Banana" });


Here we add 5 CheckBox control to ListBox.


I hope this introduction would help you to understand basics ListBox control and some important properties. In next article we would look at Data Binding in ListBox control.

Monday, 11 February 2013

Passed Microsoft Certification exam in WPF

I am very happy while writing this post as I cleared my Microsoft Certification exam MCTS 70-502 (Windows Presentation Foundation using Microsoft .net framework 3.5) with a score of 940 out of 1000. 700 was the passing criteria for the exam.

It was a good learning experience overall. While preparing for the exam I learned several new concepts, features and programming tips. I used to write some code samples along with reading the book that helped me to get some hand-on the topics. So preparing for the exam solved both purpose of getting certified as well as increasing my confidence level in WPF.

When I talked about my certification to my friends, few of my friends were inspired and asked me to guide for the certification process. So here I am providing some information.

Preparing for the Exam

  • As a first step, visit Microsoft learning and certification website to search for the certification that you would like to appear. Here is the link for MCTS Exam 70-502.
  • Go through the details provided for the exam. Preparation material section would provides details of online courses offered by microsoft related to the  exam and books to refer. I purchased recommended Microsoft Press book (“MCTS Self-Paced Training Kit (Exam 70-502): Microsoft® .NET Framework 3.5—Windows® Presentation Foundation”). This book has good contents and organized properly. This book is also accompanied with CD that contains e-Book (electronic version of book) and Practice Tests.
  • Read the book properly, practice some code while reading to get hands-on of the topics and take practice tests at the end of each lesson in the book.
  • Also refer online materials, blogs, MSDN website to explore more on WPF topics.
  • Once you are done with preparation, install the practice tests provided in the CD. Practice test contains lots of questions to exhaust you. But you will also have a good learning while practicing the questions. Also search practice questions (exam dumps) online. They are very useful while taking exam.

Taking the exam

Prometric is the authorized testing center for taking microsoft certification exams.

  • Register on Prometric website. This will create your login and generate unique Promteric ID for you. An email will be send with registration details. Use login details to log into the website.
  • Check if Microsoft is offering “Second Shot Offer” in the duration when you are taking exam. If you fail the exam in first attempt, Second Shot offer allows you to take the exam free for the second time after 15 days of taking exam for first time. Registering for the Second Shot Offer is as simple as filling a small online form and this will instantly generate Voucher code for you and also email you the same. Use this Voucher code while registering for the exam.
  • In Prometric website, Locate the Test Center near you, book you slot (date and time) for the exam and register for the exam. You can get exact exam fees details on Prometric website after selecting the exam number.
  • Visit the Prometric testing center at the scheduled time and take you exam.

I hope this information helps you while preparing for the exam.

Wishing you best luck for you exam.

Saturday, 17 November 2012

XAML

XAML stands for Extensible Application Markup Language and pronounced as "zammel”.

XAML is the programming language introduced in .net framework 3.0 to create rich user interface for WPF, Silverlight and Windows Phone applications.

XAML is XML based markup language to instantiate and initialize .net objects

Below diagram provides a simple overview of WPF - XAML

As we can see in above image,

XAML Elements are arranged in hierarchy manner. XAML elements contains other nested elements. This creates Logical Tree of controls in User Interface.

XAML Root Element:

Every XAML document has root/top element. In WPF, Window is the top level element. In Silverlight UserControl is the top level element.

XAML Namespaces:

CLR namespace are imported into XAML using xmlns attribute. Once CLR namespace is imported into XAML, classes of that namespace become available in XAML for use. In WPF, there are 2 standard namespaces that are imported into XAML.

1. http://schemas.microsoft.com/winfx/2006/xaml/presentation is related to core WPF namespace which contains all WPF Classes including WPF Controls that we use to construct User Interface. This namespace is declared without any prefix, marking it as default namespace for the document. Hence we can use all WPF controls in XAML without using any prefix.
2.   http://schemas.microsoft.com/winfx/2006/xaml is XAML namespace that defines the XAML keywords. This namespace is declared using prefix “x”. Hence any class in this namespace can be referred using x:ElementName.

XAML Elements:

Every Element in XAML maps to an instance of .net class.

<Button />

<Button /> syntax creates an instance of Button class using parameterless constructor. XAML relies on parameterless constructors to create an instance of class and hence classes that needs to be used in XAML must provide parameterless constructor. With WPF 4.0, it is also possible to pass arguments to constructors.


XAML Attributes:


Attribute of XAML Element maps to properties of .net class.

<Button Content="Home" Width="150" Height="50" Background="LightBlue">

Attributes like Content, Width, Height and Background maps to Button control properties respectively.


Property Element Syntax:
In above example, we have used inline attributes to set properties of a control. Ex: Content = “Home”. Here we set simple string as value for Content property. But what if we wish to assign a complex object to property. Ex: A Button that has Image and Text as Content. This can be done using Property Element Syntax. Each property can be set using element rather than attributes.

<Button Width="150" Height="60">
<Button.Content>
<StackPanel Orientation="Horizontal">
<Image Source="Home.png" Stretch="None"></Image>
<TextBlock Text="Home" VerticalAlignment="Center" Margin="10" FontSize="14" ></TextBlock>
</StackPanel>
</Button.Content>
</Button>

Output



Another example: Create a linear gradient effect for Background property instead of simple Background = “LightBlue”.

<Button Content="Home" Width="150" Height="50">
<Button.Background>
<LinearGradientBrush StartPoint="1, 0" EndPoint="1, 1">
<GradientStop Color="LightSkyBlue" Offset="0"></GradientStop>
<GradientStop Color="White" Offset="1"></GradientStop>
</LinearGradientBrush>
</Button.Background>
</Button>

Output


 


Implicit Type Converters:


Type Converters as the name suggests would convert value from one type to other and Implicit means that conversion happens in background. WPF has lot of built-in Type Converters. Let’s see below examples to understand where Type Converters are used and how they work.

<Button Content="Home" Width="150" Height="50" Background="LightBlue" Margin="10">

Example: We set Background property of Button control as Background = “LightBlue”. Now if we see Background property declaration in System.Windows.Controls.Control class then we find below.


Quick Tip: Write this.Background in code behind, move the cursor over Background and press F2 or “Go To Definition” which will take you to the property declaration.

public Brush Background { get; set; }

So Background property expects “Brush” object as value and we have assigned simple string to Background property. Here comes Built-In Type Converter that converts “LightBlue” string value to “System.Windows.Media.Brushes.LightBlue”.


Note: “System.Windows.Media.Brushes.LightBlue” is Named brush in WPF which internally returns an instance of SolidColorBrush of Color LightBlue.


Another example: Margin = “10”.


Now if we see Margin property declaration in System.Windows.FrameworkElement class then we find below.

public Thickness Margin { get; set; }

Margin property expects “Thickness” object as value and we assign value as 10. So Built-In type converter converts “10” to something as “new Thickness(10, 10, 10, 10)”.


OK. So how does XAML Parser decide which Type Converter to be used. XAML Parser checks for 2 places to identify Type Converter to be used.



1. Property Declaration: XAML Parser looks at property declaration for TypeConverter attribute. Margin property declaration below does not have have any information of TypeConverter.

public Thickness Margin { get; set; }


2. Class Declaration of related Data Type: If no information found in property declaration, XAML Parser looks at Class Declaration of related Data Type. In case of “Margin” property, data type is Thickness. So let’s check the Thickness class declaration.


[Localizability(LocalizationCategory.None, Readability = Readability.Unreadable)]
[TypeConverter(typeof(ThicknessConverter))]
public struct Thickness : IEquatable<Thickness>
{
// Actual Code. Omitted for simplicity.
}


Here XAML Parser finds TypeConverter attribute with ThicknessConverter as the actual Type Converter to be used.


If no TypeConverter is found and if there is data type mismatch then XAML Parser throws error.


Same way, there are several other built-in converts being used in WPF.


Markup Extensions


Till now we have set hard code values for attributes/properties in XAML. Many times we also need to set property values to an existing object, to some other control properties or set dynamic value. In such scenarios, Markup Extensions are very useful. Markup Extensions are like Placeholders for actual values that are retrieved at run time. Markup Extension are specified between using curly braces { }.



StaticResource Markup Extension example


We have seen an example above where we created linear gradient effect for Background property directly in Button control using Property Element Syntax. We would do that slightly differently.


Add linear gradient effect as an object to resource dictionary

<Window.Resources>        
<LinearGradientBrush x:Key="BlueWhiteGradient" StartPoint="1, 0" EndPoint="1, 1">
<GradientStop Color="LightSkyBlue" Offset="0"></GradientStop>
<GradientStop Color="White" Offset="1"></GradientStop>
</LinearGradientBrush>
</Window.Resources>

Use linear gradient effect object using StaticResource Markup Extension

<Button Content="Home" Width="150" Height="50" Margin="10" Background="{StaticResource ResourceKey=BlueWhiteGradient}"></Button>

So here we used StaticResource Markup Extension to bind Background property of Button control to already defined LinearGradientBrush object.



Binding Markup Extension example


Binding is widely used Markup Extension for Data Binding UI controls to .net object properties. Here is a simple example of binding Text property of TextBox control to Name property of custom employee object.

<TextBox Text="{Binding Path=Name}"></TextBox>

There are several different Markup Extension that are used for different purpose. Refer separate post that discuss all Markup Extension in detail.


Attached Properties


Each control provides their own set of properties. Attached properties are those properties which are not provided by the control itself but they are provided by their parent control and are used by child controls to specify their position and behaviors with respect to parent control.

<Grid>        
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="Enter Name:" Margin="10"></TextBlock>
<TextBox Grid.Row="0" Grid.Column="1" Height="30" Margin="5"></TextBox>
</Grid>

In this example, Row and Column property are not provided by TextBlock and TextBox control, but they are provided by Grid control. TextBlock and TextBox control uses Grid.Row and Grid.Column to specify its location in Grid control.


Now after understanding some basics of XAML language, we should be able to co-related advantages of XAML.


Advantages of XAML



  • XAML code is lesser, easier to read and understand
  • XAML allows organizing controls in hierarchy manner
  • XAML provided better separation of concerns by separating User Interface and Application/Business logic. User Interface is created using XAML and programming language like C#, VB.net are used to write code for application functionalities.
  • Visual tools like Microsoft Expression Blend are widely used for creating rich UI applications.  Microsoft Expression Blend generate XAML code which can be directly used in WPF applications.
  • XAML introduced concept of declarative programming with dependency properties and powerful data binding