1

Expectations

My control should appear as shown in Figure 1. After clicking on the button titled "Second" should contents of the control change, as shown in Figure 2. In this figure the state should be content again to change back after sending the key Enter the text box.

Solution

I created two DataTemplate. These DataTemplates should change based on changes in the properties IsEditable. Default DataTemplate is called CompactDataTemplate and should be used when the value IsEditable is equal FALSE. When the IsEditable turns TRUE, the EditableDataTemplate should be used.

File TestUserControl.xaml

<UserControl x:Class="JP4.Controls.TestControl"
         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" 
         d:DesignHeight="26" d:DesignWidth="200" Style="{DynamicResource TestControlStyle}">
<UserControl.Resources>

CompactDataTemplate

<DataTemplate x:Key="CompactDataTemplate" DataType="{x:Type UserControl}">
    <StackPanel Orientation="Horizontal">
        <Button Content="First Button" />
        <Button Content="Second Button" Click="SecondButton_Click" />
    </StackPanel>
</DataTemplate>

EditableDataTemplate

<DataTemplate x:Key="EditableDataTemplate" DataType="{x:Type UserControl}">
    <StackPanel Orientation="Horizontal">
        <TextBox Text="Press enter" />
    </StackPanel>
</DataTemplate>

TestControlStyle contains trigger that should firing in case IsEditable has been changed

<Style x:Key="TestControlStyle" TargetType="{x:Type UserControl}">
        <Setter Property="ContentTemplate" Value="{StaticResource CompactDataTemplate}" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type UserControl}">
                    <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
                        <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    </Border>
                    <ControlTemplate.Triggers>
                        <DataTrigger Binding="{Binding IsEditable}" Value="true">
                            <Setter Property="ContentTemplate" Value="{StaticResource EditableDataTemplate}" />
                        </DataTrigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>

            </Setter.Value>
        </Setter>
    </Style>
</UserControl.Resources>

</UserControl>

File TestUserControl.xaml.cs

using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;

namespace TestControl
{
/// <summary>
/// Interaction logic for TestControl.xaml
/// </summary>
public partial class TestUserControl : UserControl, INotifyPropertyChanged, INotifyPropertyChanging
{
    /// <summary>
    /// Constructors
    /// </summary>
    public TestUserControl()
    {
        InitializeComponent();
    }

    // Properties
    private bool _IsEditable;

    public bool IsEditable
    {
        get { return _IsEditable; }
        set
        {

            _IsEditable = value;
            NotifyPropertyChanged("IsEditable");
        }
    }

    // Controls events
    private void SecondButton_Click(object sender, RoutedEventArgs e)
    {
        IsEditable = true;
    }

    private void TextBox_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
    {
        if (e.Key == System.Windows.Input.Key.Enter)
            IsEditable = false;
    }

    // INotifyPropertyChanged implementation
    public void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    public void NotifyPropertyChanging(string propertyName)
    {
        if (PropertyChanging != null)
            PropertyChanging.Invoke(this, new PropertyChangingEventArgs(propertyName));
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public event PropertyChangingEventHandler PropertyChanging;


  }
}

MainWindow.xaml

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:TestControl" x:Class="TestControl.MainWindow"
    Title="MainWindow" Height="170" Width="328">
    <Grid>
        <local:TestUserControl HorizontalAlignment="Left" Margin="76,57,0,0" VerticalAlignment="Top" Width="148"/>
    </Grid>
</Window>

and finaly MainWindow.xaml.cs

using System.Windows;

namespace TestControl
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }
}
}

Hope, now it is clear, what I want. I want to change ContentTemplate of my UserControl. This change should be fired by trigger that is watching property IsEditable.

Issue

The IsEditable property is changing, but the trigger is not firing. Where is the problem?

Im sorry for my previous unclear post.

All Project files possible to download from same location as Figures just change filename to TestControl.zip (cannot post more than two links)

Miroslav Endyš
  • 154
  • 1
  • 8
  • Without a good code example, I don't fully understand what you're trying to accomplish. See http://stackoverflow.com/help/mcve. Using the code you've provided and trying to guess how you're using it, I could not even get the initial template to be displayed. I.e. the `UserControl` is displayed without any templated data. – Peter Duniho Dec 06 '14 at 00:52
  • How about [DataTemplateSelector](http://msdn.microsoft.com/en-us/library/system.windows.controls.datatemplateselector(v=vs.110).aspx) ? – Alex F Dec 07 '14 at 11:40

1 Answers1

1

Resolved!!!

I just put as the content of my user control ContentControl

<ContentControl Style="{StaticResource UserControlStyle1}" />

Style of the ContentControl looks like this:

<Style x:Key="UserControlStyle1" TargetType="{x:Type ContentControl}">

Here is defined default template

        <Setter Property="ContentTemplate" Value="{StaticResource CompactStyle}" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ContentControl}">
                    <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
                        <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    </Border>

Here is the trigger that is working pretty well

                    <ControlTemplate.Triggers>
                        <DataTrigger Binding="{Binding IsEditable, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:PathNavigator}}}"  Value="True">
                            <Setter Property="ContentTemplate" PresentationTraceSources.TraceLevel="High" Value="{StaticResource EditableStyle}"  />
                        </DataTrigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>

            </Setter.Value>
        </Setter>
    </Style>

Of course, I removed the style from UserControl

Miroslav Endyš
  • 154
  • 1
  • 8