RSS Feed

Activity Tracker – WPF DataBinding the TabControl with TreeView

In the first post about Activity Tracker, I have created a simple style for my application. In this post, I want to show DataBinding. With this feature, we can make a flexible connection between Model and View Layer. There is no need for code. Everything is constructed in XAML language, which is similar to the HTML Markup.

Simple Binding – DataTemplate

In the first example, we have a simple DataTemplate. It contains a structured Grid,  Button and couple of TextBlocks. By assigning to the Text Property Binding logic we are telling the Template too look for a specific property in a Class, which will be used with the Template.

1 <DataTemplate x:Key="TaskTemplate"> 2 <Grid Width="200"> 3 <Grid.ColumnDefinitions> 4 <ColumnDefinition Width="5*"></ColumnDefinition> 5 <ColumnDefinition Width="1*"></ColumnDefinition> 6 <ColumnDefinition Width="1*"></ColumnDefinition> 7 <ColumnDefinition Width="3*"></ColumnDefinition> 8 </Grid.ColumnDefinitions> 9 <TextBlock Grid.Column="0" Text="{Binding Path=Title}"/> 10 <TextBlock Grid.Column="1" Text="{Binding Path=TimeSpent}"/> 11 <TextBlock Grid.Column="2" Text="{Binding Path=TimeEstimate}"/> 12 <Button Grid.Column="3">Start</Button> 13 </Grid> 14 </DataTemplate>

Template is looking for specified properties in a collection bound to the ItemsSource Property. We can also do this by the DataContext, it’s more powerful concept for another Post.

image

HierarchicalDataTemplate

Simple DataTemplate doesn’t have the ability to automatically create a hierarchy. I could make a code and implement a logic  to get this effect but fortunately WPF have a HierarchicalDataTemplate. This special template is automatically making a hierarchical view used on the TreeViews.

1 <HierarchicalDataTemplate x:Key="TaskTemplate" 2 ItemsSource="{Binding Childrens}" DataType="{x:Type data:Task}" > 3 <Grid Width="200"> 4 <Grid.ColumnDefinitions> 5 <ColumnDefinition Width="5*"></ColumnDefinition> 6 <ColumnDefinition Width="1*"></ColumnDefinition> 7 <ColumnDefinition Width="1*"></ColumnDefinition> 8 <ColumnDefinition Width="3*"></ColumnDefinition> 9 </Grid.ColumnDefinitions> 10 <TextBlock Grid.Column="0" Text="{Binding Path=Title}"/> 11 <TextBlock Grid.Column="1" Text="{Binding Path=TimeSpent}"/> 12 <TextBlock Grid.Column="2" Text="{Binding Path=TimeEstimate}"/> 13 <Button Grid.Column="3">Start</Button> 14 </Grid> 15 </HierarchicalDataTemplate>

image

Task class contains a list of Childrens which is used in the HierarchicalDataTemplate.

1 public class Task 2 { 3 ..... 4 public List<Task> Childrens { get; set; } 5 ..... 6 }

HierarchicalDataTemplate has a property ItemsSource which is binded to Children’s property. The Template will create the root element and also elements from the Children’s List. I don’t have to worry about how it’s working. Magic happens behind the scene.

Binding TabControl Content

Every TabControl contains a TreeView, which is filled with Task Items. I wanted another Template, which would automatically inject the TreeView into TabControl.

1 <DataTemplate x:Key="TabItemTemplate"> 2 <Grid> 3 <TreeView Background="Transparent" ItemsSource="{Binding Content}" ItemTemplate="{StaticResource TaskTemplate}" > 4 </TreeView> 5 </Grid> 6 </DataTemplate>

TabItem Template creates a Transparent TreeView. It’s bound to the Content property. This is a property of Project class which is used to create a new TabItems with children’s injected to the TreeView.

1 public class Project 2 { 3 public string Title { get; set; } 4 public List<Task> Content { get; set; } 5 } 6  

Project class is a root for every Task set. It’s Title bound to the Header property of a TabItem.

1 <Grid Name="MainTree" Grid.Row="1" Grid.RowSpan="1"> 2 <TabControl Name="MainTabControl" ContentTemplate="{StaticResource TabItemTemplate}"> 3 </TabControl> 4  </Grid>

In order to bind the Title from the Project class to the TabItem the header, I had to change a tab item style a bit. The Content Presenter was replaced by the TextBlock which Text Property is bound to The Title.

1 <Style TargetType="TabItem"> 2 ..... 3 <Grid> 4 <StackPanel Orientation="Horizontal"> 5 <Border Name="Border" Padding="2" BorderBrush="Black" BorderThickness="1,1,1,1" 6 CornerRadius="10,10,0,0" Background="DarkOrange"> 7 <TextBlock Text="{Binding Path=Title}"></TextBlock> 8 </Border> 9 </StackPanel> 10 </Grid> 11 ..... 12  </Style>

When all is done I just need to  create sample data.

1 List<Task> tasks = new List<Task>() 2 { 3 new Task("test",10,"I",DateTime.Now,8,"komentarz"){TimeSpent = "0"}, 4 new Task("test",10,"I",DateTime.Now,8,"komentarz"){TimeSpent = "0"}, 5 new Task("test",10,"I",DateTime.Now,8,"komentarz"){TimeSpent = "0"}, 6 new Task("test",10,"I",DateTime.Now,8,"komentarz"){TimeSpent = "0"} 7 }; 8 9 10 InitializeComponent(); 11 tasks[0].Childrens = new List<Task>() 12 { 13 new Task("test",10,"I",DateTime.Now,8,"komentarz"){TimeSpent = "0"} 14 }; 15 16 List<Project> projects = new List<Project>() { new Project() { Content = tasks, Title = "Projekt1" }, new Project() { Title = "Projekt2" } }; 17 MainTabControl.ItemsSource = projects; 18  

And the result is :

image

Next post Timers + activity tracker logic.

Advertisements


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s