Wpf 自DataContext绑定在XAML中不起作用,但在代码隐藏中起作用

Wpf 自DataContext绑定在XAML中不起作用,但在代码隐藏中起作用,wpf,binding,datacontext,Wpf,Binding,Datacontext,当我试图通过Datacontext=“{Binding RelativeSource={RelativeSource Self}}”绑定窗口的Datacontext时,它不起作用,如果我在代码隐藏中做同样的事情,它会很好地工作。 我这么想是不是错了 与 this.DataContext=this 在代码隐藏窗口的构造函数中 XAML的完整代码是 <Window x:Class="SampleDemoListBox.MainWindow" xmlns="http://schem

当我试图通过Datacontext=“{Binding RelativeSource={RelativeSource Self}}”绑定窗口的Datacontext时,它不起作用,如果我在代码隐藏中做同样的事情,它会很好地工作。 我这么想是不是错了 this.DataContext=this 在代码隐藏窗口的构造函数中

XAML的完整代码是

  <Window x:Class="SampleDemoListBox.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:SampleDemoListBox"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525"
    DataContext="{Binding RelativeSource={RelativeSource Self}}"
    >
    <Window.Resources>
     <DataTemplate x:Key="ModelItemTemplate" >
      <StackPanel Margin="25" Orientation="Horizontal">
      <Image VerticalAlignment="Top" x:Name="ModelPicture" Width="150" 
        Source="{Binding PicturePath}"></Image>
        <Grid VerticalAlignment="Top">
           <Grid.RowDefinitions>
                 <RowDefinition></RowDefinition>
                  <RowDefinition></RowDefinition>
                  <RowDefinition></RowDefinition>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                   <ColumnDefinition></ColumnDefinition>
                   <ColumnDefinition></ColumnDefinition>
             </Grid.ColumnDefinitions>
                    <Label VerticalAlignment="Center" FontWeight="Bold" Content="Name:" Grid.Row="0" Grid.Column="0"></Label>
                    <Label VerticalAlignment="Center" FontWeight="Bold" Grid.Row="1" Grid.Column="0" Content="LastName:"></Label>
                    <Label VerticalAlignment="Center" FontWeight="Bold" Grid.Row="2" Grid.Column="0" Content="Age:"></Label>
                    <TextBlock  VerticalAlignment="Center" Grid.Row="0" Grid.Column="1" x:Name="Name" Width="120" Text="{Binding Name}" ></TextBlock>
                    <TextBlock  VerticalAlignment="Center" Grid.Row="1" Grid.Column="1" x:Name="LastName" Width="120" Text="{Binding LastName}" ></TextBlock>
                    <TextBox  VerticalAlignment="Center" Grid.Row="2" Grid.Column="1" x:Name="Age" Width="120" Text="{Binding Age}" ></TextBox>

                </Grid>
            </StackPanel>
        </DataTemplate>

      </Window.Resources>
      <Grid>
      <StackPanel>
        <ListBox x:Name="LstModels" Margin="25" ItemsSource="{Binding 
          Models}" ItemTemplate="{Binding Source={StaticResource 
           ModelItemTemplate}}"></ListBox>
           <Button Width="120" Height="40" Click="AddModel_OnClick" 
           Content="Add Model" ></Button>
       </StackPanel>
       </Grid>
       </Window>

而代码背后是

    public partial class MainWindow : Window
     {
        public ObservableCollection<Model> Models{ get; set; }
          public MainWindow()
          {
              InitializeComponent();
              Models= new ObservableCollection<Model> { new Model{ Name = 
             "Shabana", LastName = "Parveen", Age = 35, PicturePath = 
               @"Images\pic.bmp" },
             new Model { Name = "Ada", LastName = "Lovelace", Age = 37, 
             PicturePath = @"Images\AdaLovelace.bmp" }};

           // this.DataContext = this;

          }
     }
公共部分类主窗口:窗口
{
公共可观测集合模型{get;set;}
公共主窗口()
{
初始化组件();
模型=新的可观察集合{新模型{名称=
“Shabana”,LastName=“Parveen”,年龄=35岁,图片路径=
@“Images\pic.bmp”},
新型号{Name=“Ada”,LastName=“Lovelace”,年龄=37岁,
PicturePath=@“Images\AdaLovelace.bmp”};
//this.DataContext=this;
}
}

您的问题是因为您有一个空的observablecollection。如果您移动代码,它将工作:

public partial class MainWindow : Window
 {
    public ObservableCollection<Model> Models{ get; set; }
      public MainWindow()
      {

          Models= new ObservableCollection<Model> { new Model{ Name = 
         "Shabana", LastName = "Parveen", Age = 35, PicturePath = 
           @"Images\pic.bmp" },
         new Model { Name = "Ada", LastName = "Lovelace", Age = 37, 
         PicturePath = @"Images\AdaLovelace.bmp" }};

          InitializeComponent();

      }
 }
公共部分类主窗口:窗口
{
公共可观测集合模型{get;set;}
公共主窗口()
{
模型=新的可观察集合{新模型{名称=
“Shabana”,LastName=“Parveen”,年龄=35岁,图片路径=
@“Images\pic.bmp”},
新型号{Name=“Ada”,LastName=“Lovelace”,年龄=37岁,
PicturePath=@“Images\AdaLovelace.bmp”};
初始化组件();
}
}

通常,您应该考虑使用单独的类作为viewmodel和MVVM。

您观察到的行为是由于初始化视图和实例化
ObservableCollection的顺序造成的

在XAML中分配
DataContext
时,在构造函数中调用
InitilizeComponent()
时,将解析所有XAML。问题是:在解析XAML时,
Models
仍然是
null
,因为它是在调用
InitilizeComponent()后实例化的。因此,当对绑定求值时(在解析xaml时发生),所有绑定都会失败,因为要绑定到的集合为
null
。当您实例化
模型时
,视图没有意识到这一点,因为您没有实现任何通知机制

另一方面,当您在代码隐藏中分配DataContext时,您将在解析完所有XAML后执行此操作,这将强制视图在分配时评估绑定……因此它是有效的

我至少可以想到3种解决方案:

  • 更改初始化顺序
  • 正如Andy在回答中所建议的那样,如果您首先实例化
    模型
    集合,然后调用
    InitilizeComponent()
    ,它就会工作。在解析XAML时,视图将具有非空DataContext,因此所有数据都将通过绑定传播到视图

  • 实现
    INotifyPropertyChanged
    接口。
  • 这将允许您在方便的时候实例化
    模型
    ,然后引发
    属性更改
    事件以通知视图。这同样有效。但是,如果您遇到这么多麻烦,您应该真正考虑使用MVVM模式(许多在线教程)。我将把实现的细节留给您,因为有无数的示例和教程。您可以从以下几点开始:

  • 使
    模型成为依赖属性。
  • 如果您坚持在代码隐藏(而不是MVVM)中执行此操作,
    dependencProperties
    将很好地工作。依赖项属性有自己的通知机制。尽管非常冗长,但它们很容易实现。下面是一个很好的来源,但你可以通过谷歌搜索找到很多


    谢谢你,尼克,你的解释很有帮助。干杯,你的回答真的帮助我理解引擎盖下发生了什么。我计划稍后实现MVVM。现在,我正试图一步一步地理解这些概念。干杯