ListBox.ItemsSource {Binding ...} 不起作用,但如果我在代码中设置 ItemsSource,那就太棒了!
我正在尝试 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();
}
当我像这样运行应用程序时,一切都很好,主窗口上的列表框显示在 WeatherInfo ObservableCollection 中找到的项目MainVM 就像它应该的那样。
但是,当我注释掉该行,然后进入主窗口的 XAML,并在 XAML 中设置 WeatherList ListBox 的 ItemsSource 属性时,如下所示:
<ListBox x:Name="weatherList"
Grid.Row="0"
ItemContainerStyle="{StaticResource stretched}"
ItemsSource="{Binding WeatherInfo}" />
尽管我确实设置了MainWindow 到 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>
I am experimenting with WPF and I came across a problem I can't seem to figure out although I have done some work with Silverlight previously and used DataContexts, Data Bindings and INPC successfully. This time I am stuck...
I am using this code to create an instance of the application's main window:
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();
}
When I run the application like this, all is fine, the ListBox on the main window displays the items found in the WeatherInfo ObservableCollection of the MainVM like it should.
However, when I comment the line out and then go into my main window's XAML, and setup the ItemsSource property of the weatherList ListBox in XAML like so:
<ListBox x:Name="weatherList"
Grid.Row="0"
ItemContainerStyle="{StaticResource stretched}"
ItemsSource="{Binding WeatherInfo}" />
The list does not get populated as I would expect, although I do set the DataContext of the MainWindow to an instance of the MainVM (as shown in the C# code excerpt).
Could someone please explain to me, WHY?
==EDIT==
All of my Main Window's 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>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
谢谢大家提出的宝贵建议。我不知道“输出”窗口中显示了“绑定错误”,从那里我只需谷歌一下就能找到解决方案。
我遇到的问题是我尝试绑定的 WeatherInfo 项目源是公共字段,而不是属性。因此,我可以简单地将 WeatherInfo public ObservableCollection 分配给列表框的 itemssource,但我无法依赖数据绑定机制在 DataContext 中定位 WeatherInfo 属性,因为从技术上讲,WeatherInfo 并不是一个属性。添加 {get; private set;} 添加到 MainVM 中的 WeatherInfo 声明使数据绑定按预期工作,并且我不必再在代码中将 WeatherInfo 对象指定为列表框的 ItemsSource。
Thank you all for your valuable suggestion. I wasn't aware of the Binding Errors being displayed in the Output window and from there I was only one Google away from the solution.
The problem I had was that the WeatherInfo items source I was trying to bind to was a public field, not a property. Therefore, I could simply assign the WeatherInfo public ObservableCollection to the listbox's itemssource but I could not rely on the data binding mechanism to locate the WeatherInfo property in the DataContext, as WeatherInfo was not technically a property. Adding {get; private set;} to the WeatherInfo declaration in my MainVM made the data binding work as expected and I don't have to assign WeatherInfo object as ItemsSource of the listbox in code any more.
除非 ListBox 在另一个 DataContext 中,否则您的代码应该可以工作。
尝试
找出答案。
Your code should work unless ListBox is in another DataContext.
try
to find out.
[编辑:感觉很愚蠢]
好吧,抱歉,我看到您在 StartUp 中...之前很快就回答过...MainWindow 是 ListBox 所在的对象,对吗?
但是,我会检查以确保靠近 ListBox(直接父级等)的任何东西都没有自己的 DataContext。
[Edit: Feel Stupid]
Okay, sorry, I see that you're in the StartUp...answered to quickly before...MainWindow IS the object that the ListBox is in, correct?
I would check, however, to make sure that nothing closer to the ListBox (direct parent, etc.) has a DataContext of its own.
当您加载表单时,请检查
输出窗口看是否有
任何绑定错误消息。
一个很好的快速方法来确保您
DataContext 正确的是抛出一个
列表框旁边的按钮,
在窗口中将事件链接到它
代码隐藏并放置断点。
然后当你到达所说的断点时
到你眼前的窗口看一眼
通过将其强制转换到您的 DataContext 中
到视图模型:
(MainVM)DataContext
WeatherInfo 是否静态?
您可以发布您的 MainVM 目标代码吗?
When you load the form check the
output window to see if there are
any binding error messages.
A nice quick way to ensure you're
DataContext is correct is to throw a
button right next to the ListBox,
link an event to it in the Window's
codebehind and put a breakpoint.
Then when you reach said breakpoint
go to your immediate window and peek
into your DataContext by casting it
to the ViewModel:
(MainVM)DataContext
Is WeatherInfo static or not?
Can you post your MainVM object code?