我有一个像这样的用户控件:
<Grid>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding NameC}" Width="100" />
<TextBlock Text="{Binding Filename}" />
</StackPanel>
</Grid>
代码中的DP代码:
public TestUc()
{
InitializeComponent();
DataContext = this;
}
public static readonly DependencyProperty NameCProperty = DependencyProperty.Register(
"NameC", typeof(string), typeof(TestUc), new PropertyMetadata(default(string)));
public string NameC
{
get { return (string) GetValue(NameCProperty); }
set { SetValue(NameCProperty, value); }
}
public static readonly DependencyProperty FilenameProperty = DependencyProperty.Register(
"Filename", typeof (string), typeof (TestUc), new PropertyMetadata(default(string)));
public string Filename
{
get { return (string) GetValue(FilenameProperty); }
set { SetValue(FilenameProperty, value); }
}
现在,在窗口中使用它时,
这很好用:
<Window x:Class="TestDpOnUc.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:uc="clr-namespace:TestDpOnUc"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<uc:TestUc NameC="name is xxx" Filename="This is filename" />
</Grid>
但这不是:
<Window x:Class="TestDpOnUc.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:uc="clr-namespace:TestDpOnUc"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<uc:TestUc NameC="{Binding Name}" Filename="{Binding FileName}" />
</Grid>
public MainWindow()
{
InitializeComponent();
DataContext = this;
Name = "name is nafsafd";
FileName = "lkjsfdalkf";
}
private string _Name;
public string Name
{
get { return _Name; }
set
{
_Name = value;
OnPropertyChanged();
}
}
private string _FileName;
public string FileName
{
get { return _FileName; }
set
{
_FileName = value;
OnPropertyChanged();
}
}
有人可以解释一下原因吗?为什么用户控件的datacontext不会自动设置为父窗口 - 主窗口?
答案 0 :(得分:2)
这是因为DataContext = this
构造函数中的这一行UserControl
。您将DataContext
设置为您的用户控件,该控件会影响TestUc
和所有子级的默认绑定上下文,包括<uc:TestUc ... />
。所以目前
<uc:TestUc NameC="{Binding Name}" Filename="{Binding FileName}" />
将在Name
中查找FileName
和UserControl
个属性。您需要删除该行,但这将破坏用户控件中的绑定。
<TextBlock Text="{Binding NameC}" Width="100" />
<TextBlock Text="{Binding Filename}" />
将在NameC
中查找Filename
和MainWindow
。解决方法是通过RelativeSource
内的ElementName
或UserControl
绑定更改每个绑定的绑定上下文
<UserControl ... x:Name="myUserControl">
<Grid>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding ElementName=myUserControl, Path=NameC}" Width="100" />
<TextBlock Text="{Binding ElementName=myUserControl, Path=Filename}" />
</StackPanel>
</Grid>
</UserControl>
答案 1 :(得分:2)
使用DependencyProperties创建UserControl时,您必须将UserControl中的DP与ElementName-或RelativeSource Binding绑定到UserControl中的控件
<TextBlock Text="{Binding ElementName=myUserControl, Path=NameC}" Width="100" />
并且您从未设置DataContext。
DataContext = this; <-- do not do that within your UserControl
当您想要使用UserControl时,将其放在View中并将实际DataContext / Viewmodel的属性绑定到UserControl的 DependencyProperties 。
<uc:TestUc NameC="{Binding Name}" Filename="{Binding FileName}" />
答案 2 :(得分:1)
当你正在<uc:TestUc NameC="{Binding Name}" Filename="{Binding FileName}" />
时,它不会在你的UserControl的数据上下文中查看MainWindow的数据上下文。
因此,您可能希望搜索正确的元素并将其绑定。下面是一种使用ElementName
的方法,通过给像MainWindowName
这样的窗口命名。或者您也可以使用相对来源搜索其祖先。
<Window x:Class="TestDpOnUc.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:uc="clr-namespace:TestDpOnUc"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
x:Name="MainWindowName">
<Grid>
<uc:TestUc NameC="{Binding Element=MainWindowName, Path=DataContext.Name}" Filename="{Binding Element=MainWindowName, Path=DataContext.FileName}" />
</Grid>