C# 模型为“未找到属性”的UserControl绑定

C# 模型为“未找到属性”的UserControl绑定,c#,wpf,xaml,user-controls,C#,Wpf,Xaml,User Controls,我制作了一个超级简单的用户控件来浏览文件 <UserControl x:Class="DrumMapConverter.FileBrowserTextBox" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:m

我制作了一个超级简单的用户控件来浏览文件

<UserControl x:Class="DrumMapConverter.FileBrowserTextBox"
             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" 
             DataContext="{Binding RelativeSource={RelativeSource Self}}"
             mc:Ignorable="d" Height="24" d:DesignWidth="500">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <TextBlock Grid.Column="0" Name="lblLabel" Text="{Binding Label, Mode=TwoWay}" MinWidth="150"/>
        <Button Grid.Column="1" Content=" ... " Click="BrowseButton_Click"/>
        <TextBox Grid.Column="2" Name="txtFilepath" Text="{Binding FilePath, Mode=TwoWay}"/>
    </Grid>

</UserControl>
然后在我的主窗口中,我有这个

private DrumMapConverterDataModel model;
public MainWindow()
{
    InitializeComponent();
    model = new DrumMapConverterDataModel();
    DataContext = model;
}
该模型有两个属性:

private string inputFile = "";
public string InputFile
{
    get { return inputFile; }
    set { 
        inputFile = value;
        OnPropertyChanged("InputFile");
         }
}

private string outputFile = "";
public string OutputFile
{
    get { return outputFile; }
    set
    {
        outputFile = value;
        OnPropertyChanged("OutputFile");
    }
}
我在MainWindow.XAML中这样绑定

<cust:FileBrowserTextBox  Label="Input File" FilePath="{Binding InputFile}"/>
<cust:FileBrowserTextBox  Label="Output File" FilePath="{Binding OutputFile}"/>
运行它并获取此错误

System.Windows.Data错误:40:BindingExpression路径错误:在“object”FileBrowserTextBox“Name=”上找不到“InputFile”属性。BindingExpression:Path=InputFile;DataItem='FileBrowserTextBox'名称=;目标元素是'FileBrowserTextBox'名称=;目标属性为“文件路径”类型“字符串” System.Windows.Data错误:40:BindingExpression路径错误:在“object”FileBrowserTextBox“Name=”上找不到“OutputFile”属性。BindingExpression:Path=OutputFile;DataItem='FileBrowserTextBox'名称=;目标元素是'FileBrowserTextBox'名称=;目标属性为“文件路径”类型“字符串”

这基本上意味着UserControl中没有InputFile和OutputFile,但我试图将控件的FilePath属性与模型的InputFile和OutputFile绑定,为什么不起作用

提前谢谢。

当你这样做的时候

DataContext="{Binding RelativeSource={RelativeSource Self}}"
在FileBrowserTextBox中,通过更改绑定上下文覆盖继承的DataContext。这意味着它将尝试在FileBrowserTextBox控件中查找InputFile和OutputFile属性。删除该行并更改FileBrowserTextBox中的绑定,以便它们不会影响DataContext,例如,使用以下内容:

<TextBlock Grid.Column="0" Name="lblLabel" Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Path=Label}" MinWidth="150"/>
<TextBox Grid.Column="2" Name="txtFilepath" Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Path=FilePath}"/>
如果您只想更改UI,则根本不需要处理属性更改的回调。您已经在XAML中使用了绑定,它应该可以为您做到这一点,获取绑定上下文是可以的,并且上面的行只会在您使用固定值时覆盖这些绑定

DataContext="{Binding RelativeSource={RelativeSource Self}}"
在FileBrowserTextBox中,通过更改绑定上下文覆盖继承的DataContext。这意味着它将尝试在FileBrowserTextBox控件中查找InputFile和OutputFile属性。删除该行并更改FileBrowserTextBox中的绑定,以便它们不会影响DataContext,例如,使用以下内容:

<TextBlock Grid.Column="0" Name="lblLabel" Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Path=Label}" MinWidth="150"/>
<TextBox Grid.Column="2" Name="txtFilepath" Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Path=FilePath}"/>
如果您只想更改UI,则根本不需要处理属性更改的回调。您已经在XAML中使用了绑定,它应该可以为您做到这一点,使用绑定上下文是可以的,上面的行只会用固定值覆盖这些绑定

您已经在FileBrowserTextBox上将DataContext设置为自身,这使得所有默认绑定都可以在自身中搜索属性

避免使用ElementName为UserControl和bind设置DataContext:

如果要为UserControl保留DataContext,则必须更改窗口中的代码以显式指向窗口的DataContext,如下所示:

<cust:FileBrowserTextBox Label="Input File"
                         FilePath="{Binding DataContext.InputFile, 
                                   RelativeSource={RelativeSource FindAncestor, 
                                       AncestorType=Window}}"/>
代替RelativeSource,您还可以在绑定中使用ElementName,方法是为窗口指定x:Name,并使用ElementName进行绑定,就像在UserControl中解释的那样。

您已经在FileBrowserTextBox中将DataContext设置为自身,这使得所有默认绑定都在自身中搜索属性

避免使用ElementName为UserControl和bind设置DataContext:

如果要为UserControl保留DataContext,则必须更改窗口中的代码以显式指向窗口的DataContext,如下所示:

<cust:FileBrowserTextBox Label="Input File"
                         FilePath="{Binding DataContext.InputFile, 
                                   RelativeSource={RelativeSource FindAncestor, 
                                       AncestorType=Window}}"/>

除了RelativeSource,您还可以在绑定中使用ElementName,方法是为窗口指定x:Name,并使用ElementName进行绑定,就像在UserControl中解释的那样。

非常感谢,这解决了错误。我仍然存在一个问题,即模型中的属性InputFile和OutputFile根本没有修改。是否可以更改InotifyProperty?您不需要fileBrowserTextBox.txtFilepath.Text=stringe.NewValue;。事实上,如果只更改UI,则根本不需要为这些属性处理已更改的属性。您使用的绑定将为您做到这一点,这将删除绑定并使用固定值。非常感谢,这解决了错误。我仍然存在一个问题,即模型中的属性InputFile和OutputFile根本没有修改。是否可以更改InotifyProperty?您不需要fileBrowserTextBox.txtFilepath.Text=stringe.NewValue;。事实上,如果只更改UI,则根本不需要为这些属性处理已更改的属性。您使用的绑定将为您做到这一点,这将删除绑定并改用固定值。