Click here to Skip to main content
15,887,485 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
The problem I have is that I don't know how to reference a PropertyDependacy or UserControl in a ControlTemplate inside a UserControl

I have created a UserControl with several DependancyProperties. These properties are bound to various bits of data.
I want to create a ControlTemplate that will trigger on certain values of there DependancyProperties for example a different image appear on a button.

Anyway, there are reasons why I need DependancyProperties

This is a sample of what could be in my user control .. I have just shown a simple example of an effect triggered by a property change

The problem I have is I don't know how to reference a PropertyDependacy or UserControl in a ControlTemplate

0UserControl x:Class="ConCar.Controls.WPF.StopStartButton"
1  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
2  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
3  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
4  xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
5  mc:Ignorable="d" Height="60" Width="300">
6  <Grid>
7  <Button VerticalAlignment="Stretch" HorizontalAlignment="Stretch"  >
8  <Button.Template>
9    <ControlTemplate TargetType="{x:Type Button}">
10   <Grid>
12     <Image  Name="Normal" HorizontalAlignment="Left"  Width="40" Height="40" Source="Resources/started01.png"/>
14     <Image Name="Pressed" Source="Resources/RedCircle.png" Visibility="Hidden" HorizontalAlignment="Left" Width="40" Height="40" />
15     <Image Name="Disabled" Source="Resources/RedCircle.png" Visibility="Hidden" HorizontalAlignment="Left" Width="40" Height="40" />
17     <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="6 Lane Sizer" Padding="0,0,10,0" FontSize="18" />
18    </Grid>
19    <ControlTemplate.Triggers>
20      <Trigger Property="IsEnabled" Value="True">
21        <Setter TargetName="Normal" Property="Visibility" Value="Hidden"/>
22        <Setter TargetName="Pressed" Property="Visibility" Value="Visible"/>
23      </Trigger>
24      <Trigger Property="IsEnabled" Value="False">
25        <Setter TargetName="Normal" Property="Visibility" Value="Hidden"/>
26        <Setter TargetName="Disabled" Property="Visibility" Value="Visible"/>
27      </Trigger>
28    </ControlTemplate.Triggers>
29    </ControlTemplate>
30    </Button.Template>
31  </Button>
32  </Grid>
33</UserControl>

I want to replace IsEnabled with a DependancyProperty of my own choosing Line 20 and 24.
Shouldn't Line 10 be the name of the UserCoctrol that this code is in?
Posted
Updated 2-Feb-10 10:42am

1 solution

For the sample xaml, I would go with a ValueConverter for the image in the Source parameter, and it would be something like this:
Considering you have a Property that describe the state of your control as an enumerable:
MIDL
public enum ControlState
{
    Normal = 0,
    Pressed,
    Disabled
}


Then you define the ValueConverter:
MIDL
public class ControlStateToImageConverter : IValueConverter
{
    #region IValueConverter Members
    public object Convert(object value, Type targetType, 
                     object parameter, System.Globalization.CultureInfo culture)
    {
        ControlState state = (ControlState)value;
        if (state != null)
        {
            BitmapImage img = null;
            switch (state)
            {
                case ControlState.Normal:
                    img = new BitmapImage(
                       new Uri("pack://application:,,,/Resources/started01.png"));
                    break;
                default:
                    img = new BitmapImage(
                       new Uri("pack://application:,,,/Resources/RedCircle.png"));
                    break;
            }
            return img;
        }
        return null;
    }
    public object ConvertBack(object value, Type targetType,
                     object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
    #endregion
}

Add the converter to the resources of your user control:
XML
<UserControl.Resources>
    <local:ControlStateToImageConverter x:Key="ImgConverter"/>
</UserControl.Resources>


then you just do a simple binding in your image as:
XML
<Image Name="Normal" HorizontalAlignment="Left"  Width="40" Height="40" 
   Source="{Binding ElementName=self, Path=IsPressed, Converter={StaticResource ImgConverter}}"
   />


just remember to add a x:Name to your UserControl in this sample x:Name="self"

This approach gives you some advantages like you dont need to render 3 Image Controls (even if they are Hidden, they are rendered) you can track the changes to CLR properties with the INotifyPropertyChanged or use DependencyProperty which will automaticaly track the changes in the property for you. But if you are really into making a control that allow templating you should start by using a class that extends from a base control of your choice, implement the DependencyProperties that you need, add the handlers that you need and add a static constructor like this:
C#
static CustomControl1()
{
    DefaultStyleKeyProperty.OverrideMetadata(
        typeof(CustomControl1), 
        new FrameworkPropertyMetadata(typeof(CustomControl1)));
}


Remember also to add the TemplateParts that you need to use. I would strongly recomend that you read:
http://xamlcoder.com/cs/blogs/joe/archive/2007/12/13/building-custom-template-able-wpf-controls.aspx[^]
Creating a look-less custom control in WPF[^]

Hope it helps you.

All best
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900