Kev84
Kev84

Reputation: 837

How can I reference xaml Template from a Converter?

I am currently stuck on a problem assigning different templates to a control via a converter.

So I have 2 templates.

        <ControlTemplate x:Name="_templateA" x:Key="templateA">
            <StackPanel Grid.Column="0" Margin="0,0,5,0">
                <Blah />
            </StackPanel>
        </ControlTemplate>

        <ControlTemplate x:Name="_templateB" x:Key="templateB">
            <StackPanel Grid.Column="0" Margin="0,0,5,0">
                <Blah Blah />
            </StackPanel>
        </ControlTemplate>

and I have this control using this converter:

<ControlA x:Name="_controlA" >
     <Control Template="{Binding Converter={StaticResource templateConverters}}" />
</ControlA>

My Converter:

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        Object a;
        ControlTemplate template = null;

        try
        {
            a= value as ObjectA;
            if (value != null)
                template = a.useTemplate1 ? [templateA from xaml] : [templateB from xaml];
        }
        catch (Exception ex)
        {
            Debug.Assert(false, ex.ToString());
        }

        return toolbar;
    }

In my Converter, how am I able to get reference to my xaml file so that it allows me to assign it my desired template???

Thanks and Regards, Kev

Upvotes: 0

Views: 3756

Answers (5)

Pavlo Glazkov
Pavlo Glazkov

Reputation: 20746

What you are trying to accomplish is called a Template Selector. You can read about it, for example, here: http://codingbandit.com/Blog/blog/wpf-data-templates-part-4-template-selectors/

Given that, you will be defining a template selector (see ContentTemplateSelector property on your control). And its SelectTemplate method will look something like this:

public override System.Windows.DataTemplate SelectTemplate(object item, System.Windows.DependencyObject container)
{
    ControlTemplate template = null;
    ContentPresenter pres = container as ContentPresenter;

    try
    {
        if (value != null)
            template = item.useTemplate1 ? pres.FindResource("_templateA") : pres.FindResource("_templateB");
    }
    catch (Exception ex)
    {
        Debug.Assert(false, ex.ToString());
    }

    return toolbar;
}

Update: Sorry, I overlooked that you are trying to get a ControlTemplate, while template selectors are for selecting a DataTemplate. But I believe that you task can also be achieved using data templates.

If you still want to use ControlTemplate then triggers is the way to go:

<ControlTemplate x:Name="_templateA" x:Key="templateA">
    <StackPanel Grid.Column="0" Margin="0,0,5,0">
        <Blah />
    </StackPanel>
</ControlTemplate>

<ControlTemplate x:Name="_templateB" x:Key="templateB">
    <StackPanel Grid.Column="0" Margin="0,0,5,0">
        <Blah Blah />
    </StackPanel>
</ControlTemplate>

<Style x:Key="MyControlStyle" TargetType="[x:Type Control}">
   <Setter Property="Template" Value="{StaticResource templateB}"/>
   <Style.Triggers>
       <DataTrigger Binding="{Binding useTemplate1}" Value="True">
           <Setter Property="Template" Value="{StaticResource templateA}"/>
       </DataTrigger>
   </Style.Triggers>
</Style>

And you control:

<ControlA x:Name="_controlA" >
     <Control Style="{StaticResource MyControlStyle}" />
</ControlA>

Upvotes: 1

Snowbear
Snowbear

Reputation: 17274

Maybe you should think on some other implementation but here is what you're asking for:

your converter code:

public class MyConverter : IValueConverter
{
    public ControlTemplate TemplateA { get; set; }
    public ControlTemplate TemplateB { get; set; }

    ... Convert methods using TemplateA and TemplateB properties...
}

usage in XAML:

<UserControl.Resources>
    <!-- templates with 'templateA' and 'templateB' keys -->
    <Converters:MyConverter x:Key="templateConverters" TemplateA="{StaticResource templateA}" TemplateB="{StaticResource templateB}" />
<UserControl.Resources>

...

<ControlA x:Name="_controlA" >
    <Control Template="{Binding Converter={StaticResource templateConverters}}" />
</ControlA>

Upvotes: 10

jonathanpeppers
jonathanpeppers

Reputation: 26495

I think you can accomplish this better with DataTriggers:

    <ControlTemplate>
        <StackPanel Name="TemplateA" Grid.Column="0" Margin="0,0,5,0">
            <Blah />
        </StackPanel>
        <StackPanel Name="TemplateB" Grid.Column="0" Margin="0,0,5,0">
            <Blah Blah />
        </StackPanel>

        <ControlTemplate.Triggers>
        <DataTrigger Binding="{Binding YourProp}" Value="1">
          <Setter TargetName="TemplateA" Property="Visibility" Value="Visible" />
          <Setter TargetName="TemplateB" Property="Visibility" Value="Collapsed" />
        </DataTrigger>
        <DataTrigger Binding="{Binding YourProp}" Value="0">
          <Setter TargetName="TemplateA" Property="Visibility" Value="Collapsed" />
          <Setter TargetName="TemplateB" Property="Visibility" Value="Visible" />
        </DataTrigger>
        </ControlTemplate.Triggers>

    </ControlTemplate>

This is off the top of my head, so TargetName might be SourceName, etc.

Upvotes: 0

bubblez
bubblez

Reputation: 814

I think you should be able to load the XAML Resource file from the Application Resource dictionaries as described here.

Upvotes: 0

brunnerh
brunnerh

Reputation: 184376

Put your Templates in the resources of some control, give them x:Keys and call:

ControlTemplate template = someControl.FindResource("Key") as ControlTemplate;

Upvotes: 0

Related Questions