用户控件的datacontext是什么?

时间:2015-03-23 13:14:39

标签: c# wpf user-controls dependency-properties

我有一个像这样的用户控件:

 <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不会自动设置为父窗口 - 主窗口?

3 个答案:

答案 0 :(得分:2)

这是因为DataContext = this构造函数中的这一行UserControl。您将DataContext设置为您的用户控件,该控件会影响TestUc和所有子级的默认绑定上下文,包括<uc:TestUc ... />。所以目前

<uc:TestUc NameC="{Binding Name}" Filename="{Binding FileName}" />

将在Name中查找FileNameUserControl个属性。您需要删除该行,但这将破坏用户控件中的绑定。

<TextBlock Text="{Binding NameC}" Width="100" />
<TextBlock Text="{Binding Filename}"  />

将在NameC中查找FilenameMainWindow。解决方法是通过RelativeSource内的ElementNameUserControl绑定更改每个绑定的绑定上下文

<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>