C# 与DependencyProperty绑定有关的问题

C# 与DependencyProperty绑定有关的问题,c#,.net,wpf,mvvm-light,C#,.net,Wpf,Mvvm Light,我创建了一个小文件浏览器控件: <UserControl x:Class="Test.UserControls.FileBrowserControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="h

我创建了一个小文件浏览器控件:

<UserControl x:Class="Test.UserControls.FileBrowserControl"
             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" 
             mc:Ignorable="d" 
             d:DesignHeight="44" d:DesignWidth="461" Name="Control">
    <Grid Margin="3">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>
        <TextBox  Margin="3" Text="{Binding SelectedFile}" IsReadOnly="True" TextWrapping="Wrap" />
        <Button HorizontalAlignment="Right" Margin="3" Width="100" Content="Browse" Grid.Column="1" Command="{Binding BrowseCommand}" />
    </Grid>
</UserControl>
我是这样用的:

<userControls:FileBrowserControl SelectedFile="{Binding SelectedFile}" Filter="XSLT File (*.xsl)|*.xsl|All Files (*.*)|*.*"/>
<UserControl x:Class="WpfApplication1.SomeUserControl" Name="MyUserControl1" />
<TextBox Text="{Binding SelectedFile,
                RelativeSource={RelativeSource AncestorType=UserControl}}" />
那么我做错了什么

使用这个:

<userControls:FileBrowserControl SelectedFile="{Binding SelectedFile}" ...
使用此选项:

<userControls:FileBrowserControl SelectedFile="{Binding SelectedFile}" ...

请勿在UserControl内设置UserControl的DataContext:

这是错误的:

this.DataContext = someDataContext;
因为如果有人使用你的usercontrol,通常的做法是设置它的datacontext,这与你之前设置的内容相冲突

<my:SomeUserControls DataContext="{Binding SomeDataContext}" />

将使用哪一个?那要看情况了

这同样适用于Name属性。您不应将名称设置为UserControl,如下所示:

<userControls:FileBrowserControl SelectedFile="{Binding SelectedFile}" Filter="XSLT File (*.xsl)|*.xsl|All Files (*.*)|*.*"/>
<UserControl x:Class="WpfApplication1.SomeUserControl" Name="MyUserControl1" />
<TextBox Text="{Binding SelectedFile,
                RelativeSource={RelativeSource AncestorType=UserControl}}" />

因为它与

<my:SomeUserControls Name="SomeOtherName" />

解决方案:
在您的控件中,只需使用RelativeSource Mode=FindAncestor:

<TextBox Text="{Binding SelectedFile, RelativeSource={RelativeSource AncestorType="userControls:FileBrowserControl"}" />

对于您关于如何完成所有这些第三方控件的问题:它们使用TemplateBinding。但是TemplateBinding只能在ControlTemplate中使用


在usercontrol中,xaml表示usercontrol的内容,而不是ControlTemplate/

请勿在usercontrol中设置usercontrol的DataContext:

这是错误的:

this.DataContext = someDataContext;
因为如果有人使用你的usercontrol,通常的做法是设置它的datacontext,这与你之前设置的内容相冲突

<my:SomeUserControls DataContext="{Binding SomeDataContext}" />

将使用哪一个?那要看情况了

这同样适用于Name属性。您不应将名称设置为UserControl,如下所示:

<userControls:FileBrowserControl SelectedFile="{Binding SelectedFile}" Filter="XSLT File (*.xsl)|*.xsl|All Files (*.*)|*.*"/>
<UserControl x:Class="WpfApplication1.SomeUserControl" Name="MyUserControl1" />
<TextBox Text="{Binding SelectedFile,
                RelativeSource={RelativeSource AncestorType=UserControl}}" />

因为它与

<my:SomeUserControls Name="SomeOtherName" />

解决方案:
在您的控件中,只需使用RelativeSource Mode=FindAncestor:

<TextBox Text="{Binding SelectedFile, RelativeSource={RelativeSource AncestorType="userControls:FileBrowserControl"}" />

对于您关于如何完成所有这些第三方控件的问题:它们使用TemplateBinding。但是TemplateBinding只能在ControlTemplate中使用


在usercontrol中,xaml表示usercontrol的内容,而不是ControlTemplate/

主要问题是您在其构造函数中将usercontrol的DataContext设置为自身:

DataContext = this;
您不应该这样做,因为它破坏了任何基于DataContext的绑定,例如继承的DataContext值中的视图模型实例

相反,您将更改UserControl的XAML中的绑定,如下所示:

<userControls:FileBrowserControl SelectedFile="{Binding SelectedFile}" Filter="XSLT File (*.xsl)|*.xsl|All Files (*.*)|*.*"/>
<UserControl x:Class="WpfApplication1.SomeUserControl" Name="MyUserControl1" />
<TextBox Text="{Binding SelectedFile,
                RelativeSource={RelativeSource AncestorType=UserControl}}" />

现在,当您使用UserControl并编写如下绑定时

<userControls:FileBrowserControl SelectedFile="{Binding SelectedFile}" />


SelectedFile属性绑定到视图模型中的SelectedFile属性,该属性应位于从父控件继承的DataContext中。

主要问题是您在其构造函数中将UserControl的DataContext设置为自身:

DataContext = this;
您不应该这样做,因为它破坏了任何基于DataContext的绑定,例如继承的DataContext值中的视图模型实例

相反,您将更改UserControl的XAML中的绑定,如下所示:

<userControls:FileBrowserControl SelectedFile="{Binding SelectedFile}" Filter="XSLT File (*.xsl)|*.xsl|All Files (*.*)|*.*"/>
<UserControl x:Class="WpfApplication1.SomeUserControl" Name="MyUserControl1" />
<TextBox Text="{Binding SelectedFile,
                RelativeSource={RelativeSource AncestorType=UserControl}}" />

现在,当您使用UserControl并编写如下绑定时

<userControls:FileBrowserControl SelectedFile="{Binding SelectedFile}" />


SelectedFile属性绑定到视图模型中的SelectedFile属性,该属性应位于从父控件继承的DataContext中。

在我的脑海中,我听到了一个不真实的声音:
上帝般的
:)非常感谢,我不认为父控件中的绑定仍然引用子控件的DataContext。但我有点迷路了。所有这些第三方库如何使其用户控件不需要此
ElementName
?这是一个好问题。我认为这是因为他们使用CustomControls,而不是UserControls,但我不完全确定。你应该把它作为一个新问题发布。没问题:-)如果这个问题解决了你的问题,你也应该把它标记为已回答;-)谢谢。在我的脑海里我听到了一个不真实的声音:
上帝般的
:)非常感谢,我不认为父对象中的绑定仍然是指子对象的数据上下文。但我有点迷路了。所有这些第三方库如何使其用户控件不需要此
ElementName
?这是一个好问题。我认为这是因为他们使用CustomControls,而不是UserControls,但我不完全确定。你应该把它作为一个新问题发布。没问题:-)如果这个问题解决了你的问题,你也应该把它标记为已回答;-)谢谢。看起来好多了,谢谢。您似乎非常了解这些良好做法。我还有一个相关的小问题:目前这个userControl的所有逻辑都在代码中。这很普遍吗?因为它并不真正尊重我试图遵循的MVVM体系结构。UserControl通常在其代码中包含所有逻辑,至少是那些与视图相关的逻辑部分。但是,它的代码不应该(大量)修改它的视图模型。。。我是否不能将其绑定到包含这些字段的ViewModel?如答案所示,您可以将这些属性绑定到使用控件的视图模型属性。然而,UserControl的XAML也可以直接访问视图模型属性作为绑定源,但是您可能不需要在UserControl中声明其他属性。例如,如果控件的XAML将直接访问视图模型的SelectedFile属性,则控件本身不应该有额外的SelectedFile属性。这似乎更好,谢谢。您似乎非常了解这些良好做法。我还有一个相关的小问题:目前这个userControl的所有逻辑都在代码中。这很普遍吗?因为它并不真正尊重我试图遵循的MVVM体系结构。UserControl通常在其代码中包含所有逻辑,至少是那些与视图相关的逻辑部分。但是,它的代码不应该(大量)修改它的视图模型。。。我是否不能将其绑定到包含这些字段的ViewModel?如答案所示,您可以将这些属性绑定到视图模型属性,其中y