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.

<DataTemplate x:Key="TaskTemplate">
   <Grid Width="200">
      <Grid.ColumnDefinitions>
         <ColumnDefinition Width="5*"></ColumnDefinition>
         <ColumnDefinition Width="1*"></ColumnDefinition>
         <ColumnDefinition Width="1*"></ColumnDefinition>
         <ColumnDefinition Width="3*"></ColumnDefinition>
      </Grid.ColumnDefinitions>
      <TextBlock Grid.Column="0" Text="{Binding Path=Title}"/>
      <TextBlock Grid.Column="1" Text="{Binding Path=TimeSpent}"/>
      <TextBlock Grid.Column="2" Text="{Binding Path=TimeEstimate}"/>
      <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.</div>

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.

<HierarchicalDataTemplate x:Key="TaskTemplate" ItemsSource="{Binding Childrens}" DataType="{x:Type data:Task}">
   <Grid Width="200">
     <Grid.ColumnDefinitions>
        <ColumnDefinition Width="5*"></ColumnDefinition>
        <ColumnDefinition Width="1*"></ColumnDefinition>
        <ColumnDefinition Width="1*"></ColumnDefinition>
        <ColumnDefinition Width="3*"></ColumnDefinition>
      </Grid.ColumnDefinitions>
      <TextBlock Grid.Column="0" Text="{Binding Path=Title}"/>
      <TextBlock Grid.Column="1" Text="{Binding Path=TimeSpent}"/>
      <TextBlock Grid.Column="2" Text="{Binding Path=TimeEstimate}"/>
      <Button Grid.Column="3">Start</Button>
    </Grid>
</HierarchicalDataTemplate>

image

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

public class Task
{ 
   .....
   public List<Task> Childrens { get; set; }
   .....
}

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.

<DataTemplate x:Key="TabItemTemplate">
    <Grid>
       <TreeView Background="Transparent" ItemsSource="{Binding Content}" ItemTemplate="{StaticResource TaskTemplate}">
      </TreeView>
    </Grid>
</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.

public class Project
{ 
    public string Title { get; set; }
    public List<Task> Content { get; set; }
}

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

<Grid Name="MainTree" Grid.Row="1" Grid.RowSpan="1">
   <TabControl Name="MainTabControl" ContentTemplate="{StaticResource TabItemTemplate}"></TabControl>
</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.

<Style TargetType="TabItem"> 
    .... 
    <Grid>
      <StackPanel Orientation="Horizontal">
          <Border Name="Border" Padding="2" BorderBrush="Black" BorderThickness="1,1,1,1" 
          CornerRadius="10,10,0,0" Background="DarkOrange">
             <TextBlock Text="{Binding Path=Title}"></TextBlock>
         </Border>
      </StackPanel>
    </Grid>
    ....
</Style>

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

List<Task> tasks =new List<Task>() 
{
      new Task("test",10,"I",DateTime.Now,8,"komentarz"){ TimeSpent ="0"}, 
      new Task("test",10,"I",DateTime.Now,8,"komentarz"){ TimeSpent ="0"},
      new Task("test",10,"I",DateTime.Now,8,"komentarz"){ TimeSpent ="0"},
      new Task("test",10,"I",DateTime.Now,8,"komentarz"){ TimeSpent ="0"}
};

InitializeComponent();

tasks[0].Childrens =new List<Task>()
{ 
      new Task("test",10,"I",DateTime.Now,8,"komentarz"){ TimeSpent ="0"} 
};

List<Project> projects =new List<Project>() 
{ 
      new Project() { Content = tasks, Title ="Projekt1" }, 
      new Project() { Title ="Projekt2" } 
};

MainTabControl.ItemsSource = projects;

And the result is :

image

Next post Timers + activity tracker logic.