views:

55

answers:

4

Hello, 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>
+1  A: 

[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.

Kevin Nelson
I was puzzled by your response... it didn't seem to be of much help. And there definitely isn't any other DataContext set on any other element in my MainWindow's XAML markup. Cheers
Peter Perháč
Hmm...so if DataContext isn't getting set anywhere else, I'm at a loss. You stated that it's an ObservableCollection, so I can't see what's wrong with it. Sorry I can't be more help.
Kevin Nelson
+3  A: 

Your code should work unless ListBox is in another DataContext.

try

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

to find out.

Falcon
+1 that's cool...didn't know you could do that
Kevin Nelson
Didn't work :-( It's most frustrating because the application is so simple and because it just works fine when I set the ItemsSource in code. Am I missing some kind of Binding property in my {Binding ...} markup? Something tells me {Binding WeatherInfo} should be just fine when the DataContext of the Window is set to the MainVM which has the WeatherInfo ObservableCollection.
Peter Perháč
Post all the markup please!
Falcon
please find the markup in the edited version of the question
Peter Perháč
+1  A: 
  1. When you load the form check the output window to see if there are any binding error messages.

  2. 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

  3. Is WeatherInfo static or not?

  4. Can you post your MainVM object code?

myermian