IvenBach
IvenBach

Reputation: 583

Set the target property of a Label to an object within a custom UserControl

Simple window with only a label and custom control. When Path=ValueContainer is included and the access key is used it makes the windows notification sound but focus is not placed within the text box. Using F12 (Go To Definition) works and navigates to the TextBox.

If Path=ValueContainer is omitted no sound is made and focus doesn't change.

<Window x:Class="DebuggingSearchBoxAccessKey.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:DebuggingAccessKey"
        Title="MainWindow" Height="200" Width="200">
    <StackPanel Orientation="Horizontal">
        <Label Content="_Testing"
               Target="{Binding ElementName=searchBox, Path=ValueContainer}" />
        <local:SearchBox x:Name="searchBox" />
    </StackPanel>
</Window>

Custom control containing a TextBox I want the access key to bind to.

<UserControl x:Class="DebuggingAccessKey.SearchBox"
             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"
             xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
             xmlns:local="clr-namespace:DebuggingAccessKey"
             mc:Ignorable="d" 
             d:DesignHeight="20" d:DesignWidth="100">
    <Grid>
        <TextBox x:Name="ValueContainer"
                 Text="Bazzle"/>
    </Grid>
</UserControl>

I also implemented the Text property, as I understand it, as a DependencyProperty.

public partial class SearchBox : UserControl
{
    public SearchBox()
    {
        InitializeComponent();
    }

    public static readonly DependencyProperty TextDependencyProperty = DependencyProperty.Register(nameof(Text), typeof(string), typeof(SearchBox));

    public string Text
    {
        get => (string)GetValue(TextDependencyProperty);
        set => SetValue(TextDependencyProperty, value);
    }
}

Binding to a standard text box works, as shown below. As such it's my guess I'm missing the obvious as to what's needed for the custom control...

<StackPanel Orientation="Horizontal">
    <Label Content="_Foo" Target="{Binding ElementName=bar}" />
    <TextBox x:Name="bar" />
</StackPanel>

Upvotes: 4

Views: 537

Answers (2)

EldHasp
EldHasp

Reputation: 7918

If you do not need the advantages that DependecyProperty provides, then you can simplify code by using the usual property for read-only purposes:

using System.Windows.Controls;

namespace DebuggingAccessKey
{
    /// <summary>Interaction logic for SearchBox.xaml</summary>
    public partial class SearchBox : UserControl
        {
            public SearchBox()
            {
                InitializeComponent();
                ValueContainer = PART_ValueContainer;
            }

            public TextBox ValueContainer { get; }

        }
    }

Nevertheless, it is recommended that DependecyProperty be used for DependecyObject, although this is somewhat more complicated.

Upvotes: 1

EldHasp
EldHasp

Reputation: 7918

Bindings can only be created to PROPERTIES. But the UI elements nested in UserControl are FIELDS.

Try adding a property.

XAML:

<UserControl x:Class="DebuggingAccessKey.SearchBox"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d" 
             d:DesignHeight="20" d:DesignWidth="100">
    <Grid>
        <TextBox x:Name="PART_ValueContainer"
                 Text="Bazzle"/>
    </Grid>
</UserControl>

Code Behind:

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

namespace DebuggingAccessKey
{
    /// <summary>Interaction logic for SearchBox.xaml</summary>
    public partial class SearchBox : UserControl
    {
        public SearchBox()
        {
            InitializeComponent();
            ValueContainer = PART_ValueContainer;
        }

        public TextBox ValueContainer
        {
            get { return (TextBox)GetValue(ValueContainerProperty); }
            private set { SetValue(ValueContainerPropertyKey, value); }
        }

        // Use DependencyPropertyKey to create a read-only DependencyProperty ValueContainerProperty.
        private static readonly DependencyPropertyKey ValueContainerPropertyKey =
            DependencyProperty.RegisterReadOnly(nameof(ValueContainer), typeof(TextBox), typeof(SearchBox), new PropertyMetadata(null));


        // Using a DependencyProperty as the backing store for ValueContainer.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ValueContainerProperty = ValueContainerPropertyKey.DependencyProperty;

    }
}

Upvotes: 2

Related Questions