当我尝试通过DataContext =“{Binding RelativeSource = {RelativeSource Self}}”绑定Window的Datacontext时,它不起作用,如果我在代码隐藏中做同样的事情,它工作得很好。 假设那是错误的 的 和...一样 的 this.DataContext =此 在代码隐藏窗口的构造函数中。
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;
}
}
答案 0 :(得分:2)
您正在观察的行为是由于您初始化视图并实例化ObservableCollection
的顺序。
在XAML中分配DataContext
时,在构造函数中调用InitilizeComponent()
时,将解析所有XAML。问题是:在您的XAML被解析时,Models
仍然是null
,因为它在您调用InitilizeComponent()
之后被实例化。因此,当评估Binding时(因为正在解析xaml时),所有绑定都会失败,因为您绑定的集合是null
。当您实例化Models
时,View不知道这一点,因为您尚未实现任何通知机制。
另一方面,当您在后面的代码中分配DataContext时,您可以在解析所有XAML之后执行此操作,这会强制View在分配时评估Bindings ...因此它可以正常工作。 / p>
我至少可以想到3个解决方案:
正如Andy在他的回答中建议的那样,如果你首先实例化Models
集合然后调用InitilizeComponent()
,它就会起作用。在解析XAML时,View将具有非null的DataContext,因此所有数据都将通过Bindings传播到View。
INotifyPropertyChanged
界面。 这将允许您在方便的时候实例化Models
,然后提升PropertyChanged
事件以通知视图。这也可以。但是,如果你遇到这么多麻烦,你应该真正考虑使用MVVM模式(许多在线教程)。我将把实现的细节留给你,因为那里有无数的例子和教程。您可以从以下几个开始:
From SO, nice and to the point
More elaborate explanation here
Models
成为依赖属性。 如果你坚持在后面的代码(而不是MVVM)中执行此操作,DependencyPropeties
将运行良好。依赖属性具有自己的通知机制。尽管非常冗长,但它们很容易实现。下面是一个很好的来源,但你可以通过谷歌搜索找到很多。
答案 1 :(得分:1)
您的问题是因为您有一个null 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();
}
}
您应该考虑使用单独的类作为viewmodel和MVVM。