Qwertie
Qwertie

Reputation: 17176

Tweaking a ControlTemplate without duplicating it?

I want to change the Margin of a single object (well, maybe two) in a large ControlTemplate that is deep within an Infragistics xamDataGrid. Is it possible to do this without creating a duplicate of the entire template?

Unfortunately I can't just use this FindChild() method I found on StackOverflow because the template I want to change represents a column header. FindChild() can't help modify the template, only the instantiated controls. So I can use that method to find and modify the first column header, but the other columns are not affected. I could modify the code to find all of the headers, but if I ever decide to modify the set of columns, I expect that any new columns would be instantiated from the original template and would not include the desired change.

If what I want to do is impossible, that's okay, I just want someone to tell me so :)

Upvotes: 1

Views: 264

Answers (3)

Danield
Danield

Reputation: 125433

If margin is the only difference between the control templates then I suppose you could write an attached property to deal with this say 'AttachedMargin'. On the control give AttachedMargin a value, and use this value inside your Control Template.

Example code:

AttachedMargin Attached property:

using System.Windows;

namespace MarginProject
{
    public class AttachedProperties
    {
        public static Thickness GetAttchedMargin(DependencyObject obj)
        {
            return (Thickness)obj.GetValue(AttchedMarginProperty);
        }

        public static void SetAttchedMargin(DependencyObject obj, Thickness value)
        {
            obj.SetValue(AttchedMarginProperty, value);
        }

        // Using a DependencyProperty as the backing store for AttchedMargin.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty AttchedMarginProperty =
            DependencyProperty.RegisterAttached("AttchedMargin", typeof(Thickness), typeof(AttachedProperties), new UIPropertyMetadata(new Thickness(0)));       
    }
}

XAML:

<Window x:Class="MarginProject.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:attprops="clr-namespace:MarginProject"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <ControlTemplate x:Key="SimpleButton"  TargetType="{x:Type Button}">
            <Grid>
                <Border Name="BackgroundBorder" Background="{TemplateBinding Background}" BorderBrush="Black" BorderThickness="0,0,1,1" CornerRadius="4"  />
                <Border Name="HighlightBorder" BorderBrush="White" BorderThickness="1,1,0,0" CornerRadius="4" />
                <TextBlock  VerticalAlignment="Center" HorizontalAlignment="Center" Text="{TemplateBinding Content}" Margin="{Binding Path=(attprops:AttachedProperties.AttchedMargin), RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" />
            </Grid>
        </ControlTemplate>

        <Style TargetType="{x:Type Button}">
            <Setter Property="Width" Value="100" />
            <Setter Property="Height" Value="30" />
            <Setter Property="Background" Value="LightBlue" />
            <Setter Property="Template" Value="{StaticResource SimpleButton}" />
        </Style>

    </Window.Resources>
    <StackPanel>
        <Button Content="Hello WPF!" attprops:AttachedProperties.AttchedMargin="25,0,0,0" />
        <Button Content="Hello WPF!" />
    </StackPanel>

</Window>

Upvotes: 1

N_A
N_A

Reputation: 19897

Not sure if this hits everything you need, but, for the style property, you can use the BasedOnproperty when declaring a style and use the style of the control template.

<Style x:Key="Style1">
  <Setter Property="Control.Background" Value="Yellow"/>
</Style>

<Style x:Key="Style2" BasedOn="{StaticResource Style1}">
  <Setter Property="Control.Foreground" Value="Blue"/>
</Style>

Upvotes: 0

brunnerh
brunnerh

Reputation: 184326

Saying that something is not possible is always hard as there are many ways to approach a problem and one would need to know all of them.

Well, in this case i would say that modifying a template might be possible in theory using a lot of reflection meddling with internal components whose implementation one should not rely on, so in practice it probably is impossible.

Unless the template is defined in code (which is unlikely) you will end up with a ControlTemplate that has no VisualTree but a Template which is a TemplateContent, about which the documentation has to say the following:

This class has no public API in .NET Framework 4.

As mentioned you could try to modify this using reflection but i would not recommend doing so at all and i cannot give you any direction on it as i did not try to do that so far.

Upvotes: 1

Related Questions