ArghArgh
ArghArgh

Reputation: 373

Create a custom template as ResourceDictionary and access it from codebehind

I need to create a simple CRUD, and i want to reuse the same "template" in different pages.

MyCrud.xaml (the template)

<ResourceDictionary 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

<!-- disegno la mia crud-->
<DataTemplate x:Key="MyCrud">
    <StackPanel>
        <StackPanel Orientation="Horizontal" Margin="0,20,0,20">
            <TextBlock Text="Code"  FontWeight="Bold" Width="150" FontSize="24"/>
            <TextBox x:Name="edtCode" InputScope="Number" Width="300" Margin="20,0,20,0" HorizontalAlignment="Left"/>
        </StackPanel>
        <StackPanel Orientation="Horizontal" Margin="0,20,0,20">
            <TextBlock Text="Vin" FontWeight="Bold" Width="150" FontSize="24"/>
            <TextBox x:Name="edtVin" Width="300" Margin="20,0,20,0" HorizontalAlignment="Left"/>
        </StackPanel>
        <StackPanel Orientation="Horizontal" Margin="0,20,0,20">
            <TextBlock Text="Url" FontWeight="Bold" Width="150" FontSize="24"/>
            <TextBox x:Name="edtUrl" Width="300" Margin="20,0,20,0" HorizontalAlignment="Left"/>
        </StackPanel>
    </StackPanel>
</DataTemplate>

Then I registered it in my App.xaml

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="View/MyCrud.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>

So now I want to put it in a page, and use it in my SearchPage.xaml

SearchPage.xaml

<Page ...bla bla bla>
<ContentControl x:Name="MyTemplate" Content="{Binding}" ContentTemplate="{StaticResource MyCrud}" />
</Page>

At the moment the Layout works perfectly

The questions are:

  1. How can I access the TextBox? For example the one called edtVin from codebehind of SearchPage.
  2. Why is TextBox p= GetTemplateChild("edtVin") as TextBox; always null?
  3. I found this solution, is it the best one?

Thanks!

Upvotes: 2

Views: 1289

Answers (2)

Fede
Fede

Reputation: 44048

"Create a proper ViewModel and use proper DataBinding and all your problems will magically disappear."

A DataTemplate is intended to be used as a "Visual Representation of a Certain Data Element".

There is no need to "access" any UI elements in procedural code in WPF. Whatever modifications to any properties of these elements should be done using proper DataBinding, otherwise, if you manually modify the UI elements' properties (without modifying the corresponding underlying Data Item), you are basically breaking the consistency between UI and Data, and the UI elements inside the DataTemplate will no longer reflect the data inside the Data Item.

Create a simple class that represents the Data you want to show on screen:

public class MyData
{
    public string Code {get;set;}

    public string Vin {get;set;}

    public string Url {get;set;}
}

Then, in order to support two-way WPF DataBinding, have your class Implement the INotifyPropertyChanged interface.

Then, set the UI's DataContext to a relevant instance (or collection) of these items:

public MyWindow() //Window's constructor
{
   InitializeComponent();

   var list = new List<MyData>();

   //... populate the list with data here...

   DataContext = list;
}

and then simply manipulate these Data Items's properties while leaving the UI alone:

var item = list[0]; //for example

item.Code = "My New Code";

This is the correct way to work with WPF.

Upvotes: 2

Rohit Vats
Rohit Vats

Reputation: 81263

1) how can i access to the TextBox, for example the one called "edtVin" from codebehind of SearchPage?

You can get like this:

MyTemplate.ContentTemplate.FindName("edtVin", MyTemplate) as TextBox;

2) why TextBox p= GetTemplateChild("edtVin") as TextBox;

This returns null since edtVin is template child of ContentControl and not of Page.

3) i found that solution, is it the best one?

Yeah you can also use VisualTreeHelper methods as well. Add them as utility functions in your project so that it can be accessed from anywhere in the code.

Upvotes: 1

Related Questions