{"id":651,"date":"2013-07-28T11:56:49","date_gmt":"2013-07-28T11:56:49","guid":{"rendered":"http:\/\/putridparrot.com\/blog\/?p=651"},"modified":"2013-07-29T11:56:58","modified_gmt":"2013-07-29T11:56:58","slug":"datatemplates-and-datatriggers-in-wpf","status":"publish","type":"post","link":"https:\/\/putridparrot.com\/blog\/datatemplates-and-datatriggers-in-wpf\/","title":{"rendered":"DataTemplates and DataTriggers in WPF"},"content":{"rendered":"<p>One of the cool features of WPF is the way we can define a UI based upon the data type used.<\/p>\n<p>For example, assuming a very simple view model<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic class PersonViewModel : ReactiveObject\r\n{\r\n   private string firstName;\r\n   private string lastName;\r\n   private int age;\r\n\r\n   public string FirstName\r\n   {\r\n      get { return firstName; }\r\n      set { this.RaiseAndSetIfChanged(ref firstName, value); }\r\n   }\r\n\r\n   public string LastName\r\n   {\r\n      get { return lastName; }\r\n      set { this.RaiseAndSetIfChanged(ref lastName, value); }\r\n   }\r\n\r\n   public int Age\r\n   {\r\n      get { return age; }\r\n      set { this.RaiseAndSetIfChanged(ref age, value); }\r\n   }\r\n}\r\n<\/pre>\n<p>We might have a parent view model returning a PersonViewModel type or maybe an ItemsControl that has an ObservableCollection of PersonViewModel types. We can handle the bindings in the standard way but we can also associate a UI with a data type using DataTemplates.<\/p>\n<p>A simple example of this is seem with the following code<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n&lt;ResourceDictionary&gt;\r\n   &lt;Model:PersonViewModel x:Key=&quot;model&quot;\/&gt;\r\n&lt;\/ResourceDictionary&gt;\r\n\r\n&lt;Button Content=&quot;{Binding Source={StaticResource model}}&quot;\/&gt;\r\n<\/pre>\n<p>With the above the button content will display the namespace.objecttype, i.e. MyTestApp.PersonViewModel which is of little use, but if we create a DataTemplate as per the following XAML, we get something more useable<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;DataTemplate DataType=&quot;{x:Type ta:PersonViewModel}&quot;&gt;\r\n   &lt;TextBlock&gt;                    \r\n      &lt;TextBlock.Text&gt;\r\n         &lt;MultiBinding StringFormat=&quot;{}{0} {1} aged {2}&quot;&gt;\r\n            &lt;Binding Path=&quot;FirstName&quot; \/&gt;\r\n            &lt;Binding Path=&quot;LastName&quot; \/&gt;\r\n            &lt;Binding Path=&quot;Age&quot; \/&gt;\r\n         &lt;\/MultiBinding&gt;\r\n      &lt;\/TextBlock.Text&gt;\r\n   &lt;\/TextBlock&gt;\r\n&lt;\/DataTemplate&gt;\r\n<\/pre>\n<p>Now our button will display the &#8220;FirstName LastName aged Age&#8221; text, where obviously FirstName, LastName and Age are taken from our view model.<\/p>\n<p><em>Note: You can use a DataTemplate against any ContentControl, so we can see this template used on a button, a label or other control that expects\/handles a ContentControl. Whereas the likes of a TextBlock&#8217;s Text property expects a string, so this will not work there.<\/em><\/p>\n<p>The DataTemplate is also used in the ItemTemplate of a ListBox (for example)<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;ListBox ItemsSource=&quot;{Binding People}&quot; \/&gt;\r\n<\/pre>\n<p>Using the above, where People is an ObservableCollection<PersonViewModel> property. The ItemTemplate of the ListBox uses the DataTemplate previously defined. Alternatively we can create the DataTemplate within the ItemTemplate as per<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n&lt;ListBox ItemsSource=&quot;{Binding People}&quot;&gt;\r\n   &lt;ListBox.ItemTemplate&gt;\r\n      &lt;DataTemplate&gt;\r\n         &lt;TextBlock&gt;\r\n            &lt;TextBlock.Text&gt;\r\n               &lt;MultiBinding StringFormat=&quot;{}{0} {1} aged {2}&quot;&gt;\r\n                  &lt;Binding Path=&quot;FirstName&quot; \/&gt;\r\n                  &lt;Binding Path=&quot;LastName&quot; \/&gt;\r\n                  &lt;Binding Path=&quot;Age&quot; \/&gt;\r\n               &lt;\/MultiBinding&gt;\r\n            &lt;\/TextBlock.Text&gt;\r\n         &lt;\/TextBlock&gt;\r\n      &lt;\/DataTemplate&gt;\r\n   &lt;\/ListBox.ItemTemplate&gt;\r\n&lt;\/ListBox&gt;\r\n<\/pre>\n<p>Along with DataTemplate we can define DataTemplate Triggers, for example<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;DataTemplate DataType=&quot;{x:Type ta:PersonViewModel}&quot;&gt;\r\n   &lt;TextBlock x:Name=&quot;text&quot;&gt;                    \r\n      &lt;TextBlock.Text&gt;\r\n         &lt;MultiBinding StringFormat=&quot;{}{0} {1} aged {2}&quot;&gt;\r\n            &lt;Binding Path=&quot;FirstName&quot; \/&gt;\r\n            &lt;Binding Path=&quot;LastName&quot; \/&gt;\r\n            &lt;Binding Path=&quot;Age&quot; \/&gt;\r\n         &lt;\/MultiBinding&gt;\r\n      &lt;\/TextBlock.Text&gt;\r\n   &lt;\/TextBlock&gt;\r\n   &lt;DataTemplate.Triggers&gt;\r\n      &lt;Trigger SourceName=&quot;text&quot; Property=&quot;IsMouseOver&quot; Value=&quot;True&quot;&gt;\r\n         &lt;Setter TargetName=&quot;text&quot; Property=&quot;Background&quot; Value=&quot;GreenYellow&quot; \/&gt;\r\n      &lt;\/Trigger&gt;\r\n   &lt;\/DataTemplate.Triggers&gt;\r\n&lt;\/DataTemplate&gt;\r\n<\/pre>\n<p>So now anything use the DataTemplate will also apply the trigger code to the UI view of this data.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>One of the cool features of WPF is the way we can define a UI based upon the data type used. For example, assuming a very simple view model public class PersonViewModel : ReactiveObject { private string firstName; private string lastName; private int age; public string FirstName { get { return firstName; } set { [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[13],"tags":[],"class_list":["post-651","post","type-post","status-publish","format-standard","hentry","category-wpf"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/651","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/comments?post=651"}],"version-history":[{"count":3,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/651\/revisions"}],"predecessor-version":[{"id":654,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/651\/revisions\/654"}],"wp:attachment":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/media?parent=651"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/categories?post=651"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/tags?post=651"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}