A DataTemplate is similar in concept to a ControlTemplate in WPF. Therefore you might be wondering what the difference is between a DataTemplate and a ControlTemplate.
Well the answer is explained here. A DataTemplate allows you to display data as per your requirements. For example until now we saw that a listbox uses the toString() method to display data within it. But now in WPF we can display images along with data inside a listbox control as an item of it (For example, changing how the control displays data can be done using a DataTemplate. It is primarily concerned with the display of data inside a control.)
Whereas the ControlTemplate is primarily concerned with the visual appearance of the Control and not with how the data is being displayed inside the control.
Now looking at our example here we will try to display artist's drawings along with their personal details such as Name, Email, Gender etc inside a Label Control.
You may find an example where the same concept is used with a ListBox control for displaying a number of items. The difference between the two is that we are trying here to display data inside a Label Control. Along with this here we have tried to use an IvalueConverter Interface that would allow us to format Gender of Artist by displaying it in "Male" or "Female" format, unlike what is stored in the database, like "M" or "F".
The following is the snapshot of that.
Talking about the IvalueConverter interface, the System.Windows.Data namespace is used to convert data from the original source to the desired format and vice versa. It contains two methods where you can write your code to display data in the format required by your needs. For example display 1 as "One", 2 as "Two" , 3 as "Three" ... like wise or displaying "Male" instead of "M", "Female" instead of "F".
The two methods are:
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
The method Convert converts the original value to the desired display value. In our case the original value would be "M" or "F" and the desired value to be displayed would be "Male" or "Female".
The next Method ConvertBack would be used for inserting the record or updating the records from the application to the original Datasource like database. So that the value to be stored would be in consistent format.
The following is the code for that.
GenderConverter.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Data;
namespace DataTempEg
{
class GenderConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string displayGen = "";
if (value.ToString().Equals("M", StringComparison.InvariantCultureIgnoreCase))
displayGen = "Male";
else
displayGen = "Female";
return displayGen;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
Artist.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
namespace DataTempEg
{
public class Artists
{
public string ArtistID { get; set; }
public string ArtistName { get; set; }
public string ArtistPainting { get; set; }
public string ArtistEmail { get; set; }
public char Gender { get; set; }
public static ObservableCollection<Artists> GetAllArtistsPaintings()
{
string[] id = { "1", "2", "3", "4", "5" };
string[] names = { "Vishal", "Rahul", "Priyanka", "Siddhesh", "Lincy" };
string[] paintingNames = { "Penguins.jpg", "Chrysanthemum.jpg", "Jellyfish.jpg", "Lighthouse.jpg", "Tulips.jpg" };
string[] emails = { "[email protected]", "[email protected]", "[email protected]", "[email protected]", "[email protected]" };
char[] genders = { 'M', 'M', 'F', 'M', 'F' };
ObservableCollection<Artists> objArtist = new ObservableCollection<Artists>();
for (byte i = 0; i < id.Length; i++)
{
objArtist.Add(new Artists()
{
ArtistID = string.Concat("A00", id[i]),
ArtistName = names[i],
ArtistPainting = string.Concat("./img/", paintingNames[i]),
ArtistEmail = emails[i],
Gender = genders[i]
});
}
return objArtist;
}
}
}
MainWindow.xaml
<Window x:Class="DataTempEg.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DataTempEg"
Title="MainWindow" Height="350" Width="525">
<Window.CommandBindings>
<CommandBinding CanExecute="CommandBinding_CanExecute" Command="New" Executed="CommandBinding_Executed"/>
</Window.CommandBindings>
<Window.Resources>
<local:GenderConverter x:Key="formatGender"/>
<DataTemplate x:Name="myDataTemp" DataType="{x:Type local:Artists}">
<Grid Name="myGrid" Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="110"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="275"/>
</Grid.ColumnDefinitions>
<Border BorderBrush="BlueViolet" BorderThickness="5" HorizontalAlignment="Left" Width="100" Height="100" Grid.Row="0" Grid.Column="0">
<Image Name="img" Width="100" Height="100" Source="{Binding Path=ArtistPainting}"/>
</Border>
<Border BorderBrush="LightBlue" BorderThickness="4" Background="Wheat" Grid.Row="0" Grid.Column="1">
<Grid Name="innerGrid">
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="20"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="250"/>
</Grid.ColumnDefinitions>
<TextBlock Name="tblName" Text="Name: " Grid.Row="0" Grid.Column="0"/>
<TextBlock Name="tblArtistName" Text="{Binding Path=ArtistName}" Grid.Row="0" Grid.Column="1"/>
<TextBlock Name="tblEmail" Text="Email:" Grid.Row="1" Grid.Column="0"/>
<TextBlock Name="tblArtistEmail" Text="{Binding Path=ArtistEmail}" Grid.Row="1" Grid.Column="1"/>
<TextBlock Name="tblGen" Text="Gender: " Grid.Row="2" Grid.Column="0"/>
<TextBlock Name="tblGender" Text="{Binding Path=Gender,Converter={StaticResource formatGender}}" Grid.Row="2" Grid.Column="1"/>
</Grid>
</Border>
</Grid>
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="41*" />
<RowDefinition Height="186*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="237*" />
<ColumnDefinition Width="266*" />
</Grid.ColumnDefinitions>
<TextBlock Name="tblSelect" Text="Select Artist: " FontSize="15" Height="20" HorizontalAlignment="Left" Grid.Row="0" Grid.Column="0"></TextBlock>
<ComboBox Name="cmbArtist" DisplayMemberPath="ArtistID" Grid.Column="1" Height="30" Width="109" HorizontalAlignment="Left" Margin="9,12,0,14"></ComboBox>
<Button Content="Show" Grid.Column="1" Height="23" Command="New" CommandParameter="{Binding ElementName=cmbArtist,Path=SelectedItem}" HorizontalAlignment="Left" Margin="157,15,0,0" Name="btnShow" VerticalAlignment="Top" Width="75" />
<Label Name="lblData" ContentTemplate="{Binding myDataTemp}" Grid.Row="1" Grid.ColumnSpan="2" Height="255" VerticalAlignment="Bottom"></Label>
</Grid>
</Window>
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
namespace DataTempEg
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
//programitically added the load event of window
this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
cmbArtist.ItemsSource = Artists.GetAllArtistsPaintings();
}
private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = cmbArtist.SelectedItem != null ? true : false;
e.Handled = true;
}
private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
{
Artists obj = (Artists)e.Parameter;
if (obj != null)
{
lblData.Content = obj;
}
}
}
}
The following is the output for it.
Until and unless you select an item from the combobox the show button will not be visible because we have applied the command binding on it.
On selection of an item from the combobox the button becomes enabled. And on a click it will generate the following output that would be our desired result or output.
Hope you liked the example and it may help you in your project.