Search code examples
wpfxamldatatemplatecontroltemplate

Access ControlTemplate (Content) from the Usercontrol in XAML


I have the following Usercontrol which I am using / referencing inside another xaml file -

<UserControl x:Class="WpfApplication2.MutuallyExclusiveToggleControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         x:Name="SpecialToggleControl"
         d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
    <Style TargetType="{x:Type ListBoxItem}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate>
                    <ToggleButton Content="{TemplateBinding ContentControl.Content}"
                        Background="{Binding ElementName=SpecialToggleControl, Path=TileBackground}"          
                        IsChecked="{Binding Path=IsSelected, RelativeSource={RelativeSource TemplatedParent}}" 
                                  Name="toggleButton"/>
                    <ControlTemplate.Triggers>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</UserControl.Resources>
<ListBox x:Name="_listBox"
    SelectionChanged="ListBoxSelectionChanged"
    SelectedItem="{Binding ElementName=SpecialToggleControl, Path=SelectedItem}"
    SelectionMode="Single" ItemsSource="{Binding ElementName=SpecialToggleControl, Path=ItemsSource}">
    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <UniformGrid Columns="{Binding ElementName=SpecialToggleControl, Path=ColumnCount}"/>
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>
</ListBox>

Question: How do I access the ToggleButton's content (which is in ControlTemplate) from the place where I am using this UserControl. For ex: say, based on the Content, I want to set the background color. I do not want to do this from inside the UserControl. I want to achieve this from the place where I am using this UserControl

Thanks in advance.


Solution

  • Ok, I will answer it. The thing was instead of ControlTemplate we should modify the ListBox's ItemTemplate and apply the same ControlTemplate as a DataTemplate.

    <ListBox x:Name="_listBox"
        SelectedItem="{Binding ElementName=SpecialToggleControl, Path=SelectedItem}"
        SelectionMode="Single" 
        ItemsSource="{Binding ElementName=SpecialToggleControl, Path=ItemsSource}">
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <UniformGrid Columns="{Binding ElementName=SpecialToggleControl, Path=ColumnCount}" Background="Beige"/>
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
        <ListBox.ItemTemplate>
            <DataTemplate>
                <ToggleButton Content="{TemplateBinding ContentControl.Content}" 
                              IsChecked="{Binding RelativeSource={RelativeSource Mode=FindAncestor, 
                                                AncestorType={x:Type ListBoxItem}},Path=IsSelected}" 
                              Name="toggleButton"/>
            </DataTemplate>
        </ListBox.ItemTemplate>
    
        <ListBox.ItemContainerStyle>
            <Style TargetType="ListBoxItem">
                <Setter Property="HorizontalContentAlignment" Value="Stretch" />
                <Setter Property="VerticalContentAlignment" Value="Stretch" />
            </Style>
        </ListBox.ItemContainerStyle>
    
    </ListBox>
    

    MainWindow.xaml (where I used this Control): (The converter "cc" will now conditionally apply the colour)

                    <WpfApplication2:MutuallyExclusiveToggleControl.Resources>
                    <Style TargetType="{x:Type ToggleButton}">
                        <Style.Setters>
                            <Setter Property="Background" Value="{Binding Converter={StaticResource cc}}"></Setter>
                        </Style.Setters>                    
                    </Style>
                </WpfApplication2:MutuallyExclusiveToggleControl.Resources>
    

    Converter Code:

    public class ColourConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if((string)value == "Buy")
            {
                return Brushes.Blue;
            }
    
            if ((string)value == "Sell")
            {
                return Brushes.Red;
            }
    
            return Brushes.White;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }