C# WPF嵌套UserControl数据上下文

C# WPF嵌套UserControl数据上下文,c#,wpf,C#,Wpf,我有两个类(内部模型和外部模型)。OuterModel包含2个InnerModel实例。我想为它们创建用户控件(InnerUserControl和OuterUserControl)。OuterUserControl包含2个InnerUserControl。但我不知道在这种情况下如何使绑定工作。 下面是我尝试做的全部代码。 请建议如何修复它以获得与最后图片相同的结果。 提前谢谢 MainWindow.xaml.cs <Window x:Class="NestedUserControl.Mai

我有两个类(内部模型和外部模型)。OuterModel包含2个InnerModel实例。我想为它们创建用户控件(InnerUserControl和OuterUserControl)。OuterUserControl包含2个InnerUserControl。但我不知道在这种情况下如何使绑定工作。 下面是我尝试做的全部代码。 请建议如何修复它以获得与最后图片相同的结果。 提前谢谢

MainWindow.xaml.cs

<Window x:Class="NestedUserControl.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:NestedUserControl"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="450">
<Grid>
    <local:OuterUserControl x:Name="test"/>
</Grid>
public class InnerModel : INotifyPropertyChanged
{
    public String Data
    {
        get { return data; }
        set { data = value; }
    }
    private string data;

    public event PropertyChangedEventHandler PropertyChanged;

    public InnerModel(string _data) => data = _data;
    public void OnPropertyChanged([CallerMemberName]string prop = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
}
public partial class InnerUserControl : UserControl
{
    public InnerUserControl()
    {
        InitializeComponent();
    }
}
public class OuterModel : INotifyPropertyChanged
{
    public InnerModel model1;
    public InnerModel model2;

    public event PropertyChangedEventHandler PropertyChanged;

    public OuterModel(string data1, string data2)
    {
        model1 = new InnerModel(data1);
        model2 = new InnerModel(data2);
    }
    public void OnPropertyChanged([CallerMemberName]string prop = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
}
public partial class OuterUserControl : UserControl
{
    public OuterUserControl()
    {
        InitializeComponent();
    }
}
InnerModel.cs

<Window x:Class="NestedUserControl.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:NestedUserControl"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="450">
<Grid>
    <local:OuterUserControl x:Name="test"/>
</Grid>
public class InnerModel : INotifyPropertyChanged
{
    public String Data
    {
        get { return data; }
        set { data = value; }
    }
    private string data;

    public event PropertyChangedEventHandler PropertyChanged;

    public InnerModel(string _data) => data = _data;
    public void OnPropertyChanged([CallerMemberName]string prop = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
}
public partial class InnerUserControl : UserControl
{
    public InnerUserControl()
    {
        InitializeComponent();
    }
}
public class OuterModel : INotifyPropertyChanged
{
    public InnerModel model1;
    public InnerModel model2;

    public event PropertyChangedEventHandler PropertyChanged;

    public OuterModel(string data1, string data2)
    {
        model1 = new InnerModel(data1);
        model2 = new InnerModel(data2);
    }
    public void OnPropertyChanged([CallerMemberName]string prop = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
}
public partial class OuterUserControl : UserControl
{
    public OuterUserControl()
    {
        InitializeComponent();
    }
}
InnerUserControl.xaml

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        var model = new OuterModel("TEST1", "TEST2");
        test.DataContext = model;
    }
}
<UserControl x:Class="NestedUserControl.InnerUserControl"
         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:NestedUserControl"
         mc:Ignorable="d" 
         d:DesignHeight="450" d:DesignWidth="450">
<Grid>
    <TextBlock Text="{Binding Path=Data}"/>
</Grid>
<UserControl x:Class="NestedUserControl.OuterUserControl"
         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:NestedUserControl"
         mc:Ignorable="d" 
         d:DesignHeight="450" d:DesignWidth="450">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <local:InnerUserControl Grid.Row="0" x:Name="inner1" DataContext="model1"/>
    <local:InnerUserControl Grid.Row="1" x:Name="inner2" DataContext="model2"/>
</Grid>
最外层模型.cs

<Window x:Class="NestedUserControl.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:NestedUserControl"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="450">
<Grid>
    <local:OuterUserControl x:Name="test"/>
</Grid>
public class InnerModel : INotifyPropertyChanged
{
    public String Data
    {
        get { return data; }
        set { data = value; }
    }
    private string data;

    public event PropertyChangedEventHandler PropertyChanged;

    public InnerModel(string _data) => data = _data;
    public void OnPropertyChanged([CallerMemberName]string prop = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
}
public partial class InnerUserControl : UserControl
{
    public InnerUserControl()
    {
        InitializeComponent();
    }
}
public class OuterModel : INotifyPropertyChanged
{
    public InnerModel model1;
    public InnerModel model2;

    public event PropertyChangedEventHandler PropertyChanged;

    public OuterModel(string data1, string data2)
    {
        model1 = new InnerModel(data1);
        model2 = new InnerModel(data2);
    }
    public void OnPropertyChanged([CallerMemberName]string prop = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
}
public partial class OuterUserControl : UserControl
{
    public OuterUserControl()
    {
        InitializeComponent();
    }
}
OuterUserControl.xaml

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        var model = new OuterModel("TEST1", "TEST2");
        test.DataContext = model;
    }
}
<UserControl x:Class="NestedUserControl.InnerUserControl"
         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:NestedUserControl"
         mc:Ignorable="d" 
         d:DesignHeight="450" d:DesignWidth="450">
<Grid>
    <TextBlock Text="{Binding Path=Data}"/>
</Grid>
<UserControl x:Class="NestedUserControl.OuterUserControl"
         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:NestedUserControl"
         mc:Ignorable="d" 
         d:DesignHeight="450" d:DesignWidth="450">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <local:InnerUserControl Grid.Row="0" x:Name="inner1" DataContext="model1"/>
    <local:InnerUserControl Grid.Row="1" x:Name="inner2" DataContext="model2"/>
</Grid>
欢迎来到SO

这里有两个问题,首先,您的内部模型需要是属性,因此将它们的声明更改为:

public InnerModel model1 {get; set;}
public InnerModel model2 {get; set;}
第二个问题是绑定,您需要这样做:

<local:InnerUserControl Grid.Row="0" x:Name="inner1" DataContext="{Binding model1}"/>
<local:InnerUserControl Grid.Row="1" x:Name="inner2" DataContext="{Binding model2}"/>


最简单的方法是在外部模型中为内部控件添加两个新属性,它们将绑定到那些无法解决问题的属性。并且用户控件已经“继承”了包含控件的数据上下文,比如窗口,所以他特别说他希望InnerUserControls绑定到InnerModel实例。谢谢,Mark!这正是我一直在寻找的。我同意你的观点,依赖属性看起来很庞大。这就是我寻找xaml解决方案的原因。@Kirill很乐意帮忙。请记住,如果您随后希望重新分配这些属性,并更新视图以反映该更改,则它们将需要支持。祝你好运