我正在尝试制作一个用户控件,其中包含一些 DependencyProperties
, 这些属性会被转发给用户控件中的子控件。经过几次尝试,我终于让它工作了。为了测试,我做了一个小例子。
在这个例子中,我有一个名为 Ctrl
的用户控件,它只包含一个 TextBox
并公开了 TextBox
的 Text
属性。这个控件用在一个窗口中,该窗口包含了一个 TextBox
和我的自定义 Ctrl
,它们都绑定到同一个属性上。
用户控件
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>
代码后台
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();
}
}
}
窗口
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>
后端代码
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();
}
}
}
问题
当我发布代码后它可以正常工作,但现在我的问题是:我做错了什么导致我需要使用绑定?
MyText="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}
当绑定Ctrl
的MyText
属性时,不能像绑定原始的TextBox
那样简单地绑定。如果不这样绑定,它将无法工作,并出现警告。
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')
我需要如何更改才能实现与原始的
TextBox
相同的绑定?
在执行期间。
Ctrl
的'content',所以它会在它的上下文中被评估。因此,正如你所说,本地的DataContext
适用。如果我在Ctrl
中有一个Grid
,我可以在此Grid
上设置DataContext
,因为绑定发生在Ctrl
中的UserControl
中。我的设置DataContext
的方式只应该用于Window
等,不适用于UserControl
。 - Andreas Wallner