我需要一些帮助。我创建了一个自定义用户控件,并将其插入到主窗口中。但是,我无法将窗口中的属性绑定到用户控件中的DependencyProperty。
这是用户控制代码。 XAML:
<UserControl x:Class="SomeExample.UCFullName"
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:local="clr-namespace:SomeExample"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<StackPanel Margin="0,0,0,0" Orientation="Vertical" >
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<StackPanel Orientation="Vertical">
<Label BorderBrush="White" BorderThickness="1" Content="First Name :" FontSize="14" FontWeight="SemiBold" Foreground="White" Height="30" HorizontalAlignment="Left" Margin="0,2,0,0" VerticalAlignment="Top" Width="100"/>
</StackPanel>
<Grid>
<TextBox Name="FirstName" BorderBrush="Black" BorderThickness="1" FontSize="14" FontWeight="SemiBold" Height="30" HorizontalAlignment="Left" Margin="2,2,0,0" MaxLength="20" VerticalAlignment="Top" Width="100" TextChanged="TxtBlock_TextChanged"/>
</Grid>
</StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<StackPanel Orientation="Vertical">
<Label BorderBrush="White" BorderThickness="1" Content="Last Name :" FontSize="14" FontWeight="SemiBold" Foreground="White" Height="30" HorizontalAlignment="Left" Margin="0,2,0,0" VerticalAlignment="Top" Width="100"/>
</StackPanel>
<Grid>
<TextBox Name="LastName" BorderBrush="Black" BorderThickness="1" FontSize="14" FontWeight="SemiBold" Height="30" HorizontalAlignment="Left" Margin="2,2,0,0" MaxLength="20" VerticalAlignment="Top" Width="100" TextChanged="TxtBlock_TextChanged"/>
</Grid>
</StackPanel>
</StackPanel>
这是背后的代码
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
namespace SomeExample
{
public partial class UCFullName : UserControl, INotifyPropertyChanged
{
#region INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
protected void Notify(string propertyName)
{
if (this.PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion INotifyPropertyChanged implementation
public string ValueFullName
{
get { return (string)GetValue(ValueFullNameProperty); }
set
{
SetValue(ValueFullNameProperty, value);
Notify("ValueFullName");
}
}
// Using a DependencyProperty as the backing store for Value. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ValueFullNameProperty =
DependencyProperty.Register("ValueFullName", typeof(string), typeof(UCFullName), new FrameworkPropertyMetadata(default(string), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public UCFullName()
{
InitializeComponent();
}
private void TxtBlock_TextChanged(object sender, TextChangedEventArgs e)
{
ValueFullName = FirstName.Text + " " + LastName.Text;
}
}
}
外观如下:
这是主窗口的代码:
<Window x:Class="SomeExample.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:SomeExample"
mc:Ignorable="d"
Title="Some Example" Height="200" Width="400">
<StackPanel Margin="0,0,0,0" Orientation="Vertical" Name="SpManual" Background="Black">
<GroupBox Header="Name" Foreground="White" FontSize="14" Name="groupBoxCoordinateStart" >
<local:UCFullName ValueFullName="{Binding Path = PropertyFullName, Mode = TwoWay, RelativeSource={RelativeSource AncestorType=UserControl}}"></local:UCFullName>
</GroupBox>
<StackPanel Name="SpBtnInsert" Orientation="Horizontal" HorizontalAlignment="Center" Visibility="Visible">
<Button Name="btnShowFullName" BorderBrush="White" BorderThickness="1" FontSize="14" FontWeight="SemiBold" Height="30" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="2,2,0,0" Background="Transparent" Content="Show Name" Foreground="White" Width="98" Click="BtnShowFullName_Click"></Button>
</StackPanel>
</StackPanel>
以及背后的代码:
using System.Windows;
namespace SomeExample
{
/// <summary>
/// Lógica de interacción para MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public string PropertyFullName { get; set; }
public MainWindow()
{
InitializeComponent();
}
private void BtnShowFullName_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Current full name :" + PropertyFullName);
}
}
}
当然,我希望当我按下按钮时,会收到一条消息,其中包含用户输入的全名。但是,我什么也没得到。
编辑:这是该问题的解决方案,适用于访问有类似问题的页面的人。
<local:UCFullName ValueFullName="{Binding Path = PropertyFullName, RelativeSource={RelativeSource AncestorType=Window}}"></local:UCFullName>
答案 0 :(得分:1)
您绑定到错误的AncestorType
。类型必须为UserControl
,而不是Window
。 Window
扩展了Control
,但没有扩展UserControl
。
<local:UCFullName ValueFullName="{Binding Path=PropertyFullName, Mode=TwoWay, RelativeSource={RelativeSource AncestorType=Window}}" />
此外,因为将Binding.Mode
设置为TwoWay
,所以绑定源PropertyFullName
必须能够将值的变化通知绑定目标ValueFullName
。为此,您需要将PropertyFullName
作为DependencyProperty
来实现双向绑定。
作为旁注: 以下代码可能有问题
public string ValueFullName
{
get { return (string)GetValue(ValueFullNameProperty); }
set
{
SetValue(ValueFullNameProperty, value);
Notify("ValueFullName"); // This line might never get called
}
}
这只是实际DependencyProperty
的CLR包装,并且不会被框架调用。在此属性上使用绑定时,包装器将永远不会被调用,因此该事件将永远不会引发。
答案 1 :(得分:0)
正如BionicCode指出的那样,您可以更改AncestorType
。另一种选择是设置窗口的DataContext
。
您可以在构造函数中完成
public MainWindow()
{
InitializeComponent();
DataContext = this;
}
或在XAML中。
<Window DataContext="{Binding Mode=OneWay, RelativeSource={RelativeSource Self}}">
这样,您不必在绑定中指定源(只要您绑定到代码隐藏属性即可)。