Woodrow Barlow
Woodrow Barlow

Reputation: 9047

How to use property triggers with dependency properties on a user control?

How do I use property triggers in conjunction with dependency properties on a user control to set style attributes on a UI element by name?

I have a custom user control, MyUserControl.xaml:

<UserControl x:Class="MyProject.MyUserControl"
             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="450" d:DesignWidth="800">
    <UserControl.Triggers>
        <Trigger Property="IsEditable" Value="True">
            <Setter Property="Visibility" Value="Collapsed" TargetName="NameField" />
            <Setter Property="Visibility" Value="Visible" TargetName="NameBox" />
        </Trigger>
        <Trigger Property="IsEditable" Value="False">
            <Setter Property="Visibility" Value="Collapsed" TargetName="NameBox" />
            <Setter Property="Visibility" Value="Visible" TargetName="NameField" />
        </Trigger>
    </UserControl.Triggers>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="auto" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="auto" />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <Label Grid.Row="0" Grid.Column="0" Content="Name" />
        <TextBlock Grid.Row="0" Grid.Column="1" x:Name="NameField" Text="{Binding Name}" />
        <TextBlock Grid.Row="0" Grid.Column="1" x:Name="NameBox" Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" />
    </Grid>
</UserControl>

And the code-behind, MyUserControl.xaml.cs:

using System.Windows;

namespace MyProject
{
    public partial class MyUserControl
    {
        public bool IsEditable
        {
            get { return (bool)GetValue(IsEditableProperty); }
            set { SetValue(IsEditableProperty, value); }
        }

        public static readonly DependencyProperty IsEditableProperty =
                DependencyProperty.Register("IsEditable", typeof(bool),
                                            typeof(MyUserControl), new PropertyMetadata(false));

        public UserDetailedUserControl()
        {
            InitializeComponent();
        }
    }
}

I include it in my main window like this:

<Window x:Class="MyProject.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:MyProject"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <local:MyUserControl />
</Window>

My intention is to be able to include it like this:

    <local:MyUserControl IsEditable="True" />

And get the TextBox instead of the TextBlock.

When I compile, I get an error in the XAML:

'IsEditable' member is not valid because it does not have a qualifying type name. (MyUserControl.xaml line 9)

I believe I need to do something to my Value attributes to set them to a literal boolean true or false, rather than the strings "True" and "False", but I'm not sure how to do that.

Edits

Andy suggests in the comments:

Something like Property="local:MyUserControl.IsEditable" where local is an xmlns for MyProject

When I do that, I get a different error on the same line, "Unkown build error: Key cannot be null".

I think this is on the right track but the syntax isn't quite right... it seems wrong to be putting namespaces inside the XAML parameter value without using curly braces.

Upvotes: 1

Views: 64

Answers (1)

Signalist
Signalist

Reputation: 44

I would use DataTriggers instead of the standard triggers so you can set the binding explicitly to the IsEditable property of the code-behind within the trigger.

Upvotes: 1

Related Questions