I'm trying to make a user control that has a few DependencyProperties which are forward to child controls in the user control. After a few trys I got this to work. For testing a made a small example.
In the example I have a user control named Ctrl that just contains a TextBox and exposes the Text property of the TextBox. This control is used in a window which contains a TextBox and my custom Ctrl which are bound to the same property.
user control
XAML
<UserControl x:Class="trying.Ctrl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" DataContext="{Binding RelativeSource={RelativeSource self}}" Height="Auto" Width="Auto"> <TextBox Text="{Binding MyText}" /> </UserControl> Code behind
using System.Windows; using System.Windows.Controls; namespace trying { public partial class Ctrl : UserControl { public static readonly DependencyProperty MyTextProperty = DependencyProperty.Register( "MyText", typeof( string ), typeof( UserControl ), new FrameworkPropertyMetadata( default(string), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)); public string MyText { get { return (string)GetValue( MyTextProperty ); } set { SetValue( MyTextProperty, value ); } } public Ctrl() { InitializeComponent(); } } } window
XAML
<Window x:Class="trying.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:cc="clr-namespace:trying" DataContext="{Binding RelativeSource={RelativeSource self}}" Title="Window1" Height="300" Width="300"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <TextBox Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Center" Text="{Binding DisplayText}" /> <cc:Ctrl Grid.Row="1" VerticalAlignment="Center" HorizontalAlignment="Center" MyText="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DisplayText}" /> </Grid> </Window> code behind
using System.Windows; using System.ComponentModel; namespace trying { public partial class Window1 : Window, INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected void NotifyPropertyChanged( string propertyName ) { if( PropertyChanged != null ) PropertyChanged( this, new PropertyChangedEventArgs( propertyName ) ); } private string m_displayText = "asdf"; public string DisplayText { get { return m_displayText; } set { m_displayText = value; NotifyPropertyChanged( "DisplayText" ); } } public Window1() { InitializeComponent(); } } } problem
How I posted the code it works. My question is now: What have I done wrong that I have to use the binding
MyText="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}} When binding the MyText property of Ctrl and can not just the simple binding like I use when binding the original TextBox?
If I don't bind this way it won't work, and I get the warning
System.Windows.Data Error: 39 : BindingExpression path error: 'DisplayText' property not found on 'object' ''Ctrl' (Name='')'. BindingExpression:Path=DisplayText; DataItem='Ctrl' (Name=''); target element is 'Ctrl' (Name=''); target property is 'MyText' (type 'String') What do I have to change that binding is possible like with the original TextBox?
during execution.