0

我正在尝试使用 WPF,但遇到了一个我似乎无法弄清楚的问题,尽管我之前已经使用 Silverlight 完成了一些工作并成功使用了 DataContexts、Data Bindings 和 INPC。这次我卡住了...

我正在使用此代码创建应用程序主窗口的实例:

protected override void OnStartup(StartupEventArgs e)
{
    base.OnStartup(e);
    MainWindow window = new MainWindow();
    var viewModel = new MainVM(); //implements INotifyPropertyChanged
    viewModel.Load("Brighton+UK");
    window.DataContext = viewModel;
    window.weatherList.ItemsSource = viewModel.WeatherInfo; //THIS WORKS
    window.Show();
}

当我像这样运行应用程序时,一切都很好,主窗口上的 ListBox 显示在 MainVM 的 WeatherInfo ObservableCollection 中找到的项目,就像它应该的那样。

但是,当我注释掉该行然后进入我的主窗口的 XAML,并在 XAML 中设置 weatherList ListBox 的 ItemsSource 属性时,如下所示:

<ListBox x:Name="weatherList" 
    Grid.Row="0" 
    ItemContainerStyle="{StaticResource stretched}" 
    ItemsSource="{Binding WeatherInfo}" />

尽管我确实将 MainWindow 的 DataContext 设置为 MainVM 的一个实例(如 C# 代码摘录中所示),但该列表并未像我预期的那样填充。

有人可以向我解释一下,为什么?

==编辑==

我所有主窗口的 XAML:

<Window x:Class="DataTemplates.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Google World Weather" 
        SizeToContent="WidthAndHeight" 
        WindowStartupLocation="CenterScreen"
        xmlns:local="clr-namespace:DataTemplates" >

    <!--Resources section-->
    <Window.Resources>

        <!--Styles-->
        <Style TargetType="Label">
            <Setter Property="FontSize" Value="24" />
            <Setter Property="Margin" Value="10,0,0,0" />
        </Style>

        <Style x:Key="stretched" TargetType="ListBoxItem">
            <Setter Property="HorizontalContentAlignment" Value="Stretch" />
        </Style>

    </Window.Resources>

    <!--Command binding definition-->
    <Window.CommandBindings>
        <CommandBinding Command="Refresh" x:Name="cmdLoadWeatherForecast" CanExecute="cmdLoadWeatherForecast_CanExecute" Executed="cmdLoadWeatherForecast_Executed" />
    </Window.CommandBindings>

    <!--UI design - layout of individual controls-->
    <Grid x:Name="LayoutRoot">
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <ListBox x:Name="weatherList" Grid.Row="0" ItemContainerStyle="{StaticResource stretched}" ItemsSource="{Binding WeatherInfo}" />

        <StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Center" Margin="10" >
            <TextBox Text="Brighton UK" Name="txtLocation" Width="200" FontSize="20" Margin="10" FocusManager.FocusedElement="{Binding txtLocation}" />
            <Button IsDefault="True" Name="btnLoadForecast" Content="Load Weather Forecast"  Command="Refresh" Margin="0,10,10,10" Padding="10"/>
        </StackPanel>

    </Grid>
</Window>
4

4 回答 4

4

谢谢大家的宝贵建议。我不知道输出窗口中显示的绑定错误,从那里我离解决方案只有一个谷歌。

我遇到的问题是我试图绑定的 WeatherInfo 项目源是一个公共字段,而不是一个属性。因此,我可以简单地将 WeatherInfo public ObservableCollection 分配给列表框的 itemssource,但我不能依赖数据绑定机制来定位 DataContext 中的 WeatherInfo 属性,因为 WeatherInfo 在技术上不是属性。添加 {get; private set;} 到 MainVM 中的 WeatherInfo 声明使数据绑定按预期工作,我不必再将 WeatherInfo 对象分配为代码中列表框的 ItemsSource。

于 2010-11-01T09:46:53.063 回答
3

除非 ListBox 在另一个 DataContext 中,否则您的代码应该可以工作。

尝试

<ListBox x:Name="weatherList" 
    Grid.Row="0" 
    ItemContainerStyle="{StaticResource stretched}" 
    ItemsSource="{Binding DataContext.WeatherInfo, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type yournamespace:MainWindow}}}" />

找出答案。

于 2010-10-29T14:25:36.443 回答
1

[编辑:感觉愚蠢]

好的,抱歉,我看到您在 StartUp... 之前快速回答... MainWindow 是 ListBox 所在的对象,对吗?

但是,我会检查以确保靠近 ListBox(直接父级等)的任何东西都没有自己的 DataContext。

于 2010-10-29T14:21:12.320 回答
1
  1. 当您加载表单时,请检查输出窗口以查看是否有任何绑定错误消息。

  2. 确保 DataContext 正确的一个很好的快速方法是在 ListBox 旁边放置一个按钮,在 Window 的代码隐藏中将一个事件链接到它并放置一个断点。然后,当您到达所述断点时,转到您的即时窗口并通过将其转换为 ViewModel 来查看您的 DataContext: (MainVM)DataContext

  3. WeatherInfo 是静态的吗?

  4. 您可以发布您的 MainVM 目标代码吗?

于 2010-10-29T15:22:35.743 回答