We pay for user submitted tutorials and articles that we publish. Anyone can send in a contribution
Learn MoreUsually, the WPF controls are declared in the .xaml file and not in the code behind (.xaml.cs file). However, we might need to use some of those controls in the code behind in order to manipulate them. How can we get the handle of such a control if it “resides” in the xaml file? Take a look at the following xaml code:
<Window x:Class="WpfApplication2.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300" MouseLeftButtonDown="window_Clicked"> <Grid> <TextBlock x:Name="fullNameControl" FontSize="20" Text="{Binding Path=FullName}"> </TextBlock> </Grid> </Window>
There is a TextBlock called fullNameControl, in the code behind I change its background color to gold when the window is clicked:
public partial class Window1 : Window { public Window1() { InitializeComponent(); this.DataContext = new DemoData(); } void window_Clicked(object sender, MouseButtonEventArgs e) { this.fullNameControl.Background = Brushes.Gold; } }
This is very straightforward, fullNameControl becomes a property of the window class so it is very simple to manipulate it. But what if we decided to create a DataTemplate which contain the TextBlock control, like this:
<Window x:Class="WpfApplication2.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:data="clr-namespace:WpfApplication2" Title="Window1" Height="300" Width="300" MouseLeftButtonDown="window_Clicked"> <Window.Resources> <DataTemplate x:Name="myTemplate" DataType="{x:Type data:DemoData}"> <TextBlock x:Name="fullNameControl" FontSize="20" Loaded="fullNameControl_Loaded" Text="{Binding Path=FullName}"> </TextBlock> </DataTemplate> </Window.Resources> <Grid> <Label Content="{Binding}"></Label> </Grid> </Window>
Now, when trying to compile the code, I get the following error: “error CS1061: ‘WpfApplication2.Window1′ does not contain a definition for ‘fullNameControl’ and no extension method ‘fullNameControl’ accepting a first argument of type ‘WpfApplication2.Window1′ could be found (are you missing a using directive or an assembly reference?)”. OK, the window class doesn’t have fullNameControl property anymore because it is declared in the DataTemplate so there must be another way to do it.
Template.Find() doesn’t work with DataTemplates: Someone suggested that I can use the Template.Find() method, but it turns out that it doesn’t work for DataTemplates, Template.Find() is only good for ControlTemplates (read more about creation of new Control Templates in How to use Microsoft Expression Blend to modify a control).
So, I googled a little bit and didn’t find much about that issue, there were 2 entries where this issue is brought up:
Finally, I came up with my own idea: subscribe to the ‘fullNameControl’ Load event (in the xaml) and save the sender as a TextBlock so from now on, we have our control handle as a class member called m_textBlock…
public partial class Window1 : Window { public Window1() { InitializeComponent(); this.DataContext = new DemoData(); } void fullNameControl_Loaded(object sender, RoutedEventArgs e) { m_textBlock = sender as TextBlock; } void window_Clicked(object sender, MouseButtonEventArgs e) { m_textBlock.Background = Brushes.Gold; } private TextBlock m_textBlock; }
When the window Click event is raised, the background color of the text block is changed to gold. This is how I can use controls which are defined inside a DataTemplate in the code behind… What do you think about my solution? Do you know any better idea? I will be glad to hear your opinions.
Tags :
ChangecontrolControlTemplteDataTemplateFindControlWPFXaml Copyright © 2012 Dev102.com
Breeze : Designed by Amit Raz and Nitzan Kupererd
Russell Mull
Said on August 8, 2008 :
A clever workaround. But if you have to use it, you’re probably doing things wrong. In my ~1 year of doing WPF, I haven’t seen anything I couldn’t solve via either more clever databinding, or by making a custom control and binding to it. The second strategy, in particular, can save large amounts of code and pain if used judiciously.
Really, if you’re using the XAML side correctly, you ought to be able to do anything you want without having to reach into the UI from the code-behind.
Shahar Y
Said on August 8, 2008 :
@ Russell Mull
I totally agree with you, if you use MVC pattern, there shall be no need to reach into the UI from the code-behind !
But sometimes your bos can decide to give the ownership of a big control which was not designed by you, and you have no time for refactoring…
Jon von Gillern
Said on August 8, 2008 :
So why not just add a trigger via a style to your template? The template doesn’t need to change (except where you want it) and you don’t have to touch code behind.
Shahar Y
Said on August 8, 2008 :
@ Jon von Gillern
Sometimes you need that a control in your DataTemplate will react to something that is in another Template…
But, in general, I agree that you should do your best to avoid touching the code behind.
If you have no other choice, you can use my “technique”
Brian
Said on October 8, 2008 :
You have hit the nail on the head. I had a control buried inside a datatemplate that used multiple datatemplates, Viewports, storyboards and ContentPresenter. Multiple instances of this control are created in a parent using databinding but I needed to adjust the height and width of this control based on external data. Using your technique turned what seemed a daunting challenge of retrieving datatemplates and such into an elegant three line of code solution.
Victor Ponomaryov
Said on December 5, 2008 :
Cool idea!
Martin Cook
Said on December 19, 2008 :
I don’t understand how this can possibly work where you have a datatemplate reused many times for example as the itemtemplate of a listboxitem?
I have a datatemplate which is 3D which has a viewport element. When the user clicks on a listbox item it spins the item on the x axis. I want the previously selected item to automatically spin back - but of course the viewport for this and other items are wrapped in each datatemplate.
Cheers,
Martin
ross
Said on December 30, 2008 :
This technique may be useful for the PasswordBox sitting on a DataTemplate.
It is very annoying because for security reasons you can’t bind to the PasswordBox.Password (its not a dependency property). Therefore the only way to get the value is by accessing the control from code, but of course you can’t easily get at the values of a datatemplate.
Sergey Galich
Said on February 23, 2009 :
Use VisualTreeHelper.GetParent((UIElement)(TemplatedParent ?? Parent))
Amit
Said on March 13, 2009 :
Guys , I have an issue with multiple resolution , Some areas get distorted on change of resoultion ,So I think to change the width , height and margin etc of inner controls dynamically , still there are few controls which lie in datatemplate and I need to access them .I just wonder how to resolve this issue !
It works with trick of setting the parameters on load event.
Can any one suggest with a better solution for the issue [Multiple Resolution] ?
Thanks,
Amit
Hamish
Said on March 18, 2009 :
This is a fantastic solution for a problem I have been having with a data template inside rowdetails of the WPF toolkit datagrid. I wanted to add a button to show or hide data on the template and I was unable to reference any of the controls… well done!
Amit
Said on March 18, 2009 :
@Amit & Hamish
I think you should also read the following post:
http://www.dev102.com/2009/03/02/tidy-up-your-xaml-and-code-behind-use-usercontrols-inside-templates/
It might also help you.
Hamish
Said on March 20, 2009 :
Thanks Amit, I did actually run into trouble with this solution as when there were multiple instances of the data plate the variable matching got very confused. I will try your suggestion.
Derek
Said on June 6, 2009 :
Wow, thanks sooo very much for these posts guys. I swear, as I try to migrate some of the complicated pieces of our enterprise applications using WPF’s awesome capabilities to remove the need to code behind access, I ran into the same need for at least some references using the ContentPresenter and many datatemplates. This really helped along with providing the necessary other options to make me feel informed in my decisions for my project.
Sudarsan Srinivasan
Said on August 14, 2009 :
Check out this method, http://msdn.microsoft.com/en-us/library/system.windows.frameworktemplate.findname.aspx
relatively simple
Daniel
Said on March 5, 2010 :
This is kind o a kids “hack”. I mean what do you do if you have a library of custom controls? On OnApplyTemplate() this approach will fail.
I agree more the binding approach, as this is walking instead of driving..
Daniel
neeraj
Said on March 5, 2010 :
Thanks Amit..that’s what i was searching for..you saved my time.
Thanks again!
God bless!
Jeen
Said on May 3, 2010 :
Hi,
But it always load the last record in TextBlock object. Can u explain how to load the selected record’s textBlock data in listbox.
Bharathi
Said on August 10, 2010 :
hi, great idea, it was very useful for me. thanks.
Richard
Said on October 19, 2010 :
Look at this msdn article:
http://blogs.msdn.com/b/wpfsdk/archive/2007/04/16/how-do-i-programmatically-interact-with-template-generated-elements-part-ii.aspx
moviepagal
Said on November 18, 2010 :
I was struggling with this problem for around 2 days. Your solution worked.
You are a genius.
Deckymcd
Said on February 8, 2011 :
You are a god. I’ll be thinking more like you from now on. Cheers.
SLAndy
Said on May 6, 2011 :
I would also like to reiterate that you are a genius. Thanks for posting this!