gpt4 book ai didi

wpf - 自 DataContext 绑定(bind)在 XAML 中不起作用,但在代码隐藏中起作用

转载 作者:行者123 更新时间:2023-12-02 03:37:12 26 4
gpt4 key购买 nike

当我尝试通过 DataContext="{BindingrelativeSource={RelativeSource Self}}"绑定(bind) Window 的 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;

}
}

最佳答案

您所观察到的行为是由初始化 View 和实例化 ObservableCollection 的顺序决定的。

当您在 XAML 中分配 DataContext 时,当您在构造函数中调用 InitilizeComponent() 时,所有 XAML 都会被解析。问题是:在解析 XAML 时,Models 仍然为 null,因为它是在调用 InitilizeComponent() 之后实例化的。因此,所有绑定(bind)都会失败,因为在评估 Binding 时(解析 xaml 时会发生这种情况),您绑定(bind)到的集合为 null。当您实例化模型时, View 不会意识到这一点,因为您尚未实现任何通知机制。

另一方面,当您在后面的代码中分配 DataContext 时,您会在解析所有 XAML 之后执行此操作,这会强制 View 在分配时评估绑定(bind)...因此它可以工作。

我至少能想到 3 个解决方案:

  1. 更改初始化顺序

正如 Andy 在他的回答中所建议的,如果您首先实例化 Models 集合,然后调用 InitilizeComponent(),它将起作用。当 XAML 被解析时, View 将有一个非空的 DataContext,因此所有数据都将通过绑定(bind)传播到您的 View 。

  • 实现 INotifyPropertyChanged 接口(interface)。
  • 这将允许您在方便的时候实例化Models,然后引发PropertyChanged 事件来通知 View 。这也同样有效。但如果你遇到这么多麻烦,你真的应该考虑使用 MVVM 模式(网上有很多教程)。我将把实现的细节留给您,因为那里有无数的示例和教程。您可以从以下几个方面入手:

    From SO, nice and to the point

    More elaborate explanation here

    From WPF Tutorial.net

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

    See this article

    关于wpf - 自 DataContext 绑定(bind)在 XAML 中不起作用,但在代码隐藏中起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49832633/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com