3
votes

I am following MVVM in C# and am attempting to display a view in a listbox.

I am setting the listbox itemsource (in code, not in binding and using the viewmodels collection) and then set the datatemplate to be my view in xaml. The issue I'm encountering is my view always loads with its default constructor values, if I remove the datacontext from the view however it loads fine.

Below is the listbox I am creating in xaml

<ListBox Name="lbCatalogues" HorizontalContentAlignment="Stretch">
     <ListBox.ItemTemplate>
         <DataTemplate>
              <view:CatalogueRowView/>
          </DataTemplate>
      </ListBox.ItemTemplate>
</ListBox>

This is the xaml for my view. If I remove the DataContext it works

<UserControl.DataContext>
    <model:CatalogueModel />
</UserControl.DataContext>

    <Grid Name="Container" >
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="50" />
        <ColumnDefinition Width="100" />
        <ColumnDefinition Width="100" />
        <ColumnDefinition Width="1*" />
        <ColumnDefinition Width="40" />
    </Grid.ColumnDefinitions>
    <!-- Catalogue_ID, UploadedTime, Client_ID, Name, Desc, Filesize -->
    <Label Name="lblCatalogueID" Content="{Binding Path=CatalogueID}" Grid.Column="0"/>
    <Label Name="lblUploadedTime" Content="{Binding Path=UploadedTime}" Grid.Column="1"/>
    <Label Name="lblCatalogueName" Content="{Binding Path=Name}" Grid.Column="2"/>
    <Label Name="lblCatalogueDescription" Content="{Binding Path=Description}" Grid.Column="3"/>
    <Label Name="lblFilesize" Content="{Binding Path=Filesize}" Grid.Column="4"/>
    <Grid/>

This is the code where I am setting the listbox ItemSource:

lbCatalogues.ItemsSource = catalogueViewModel.Records;

My question is how can I get the view to load correctly within the listbox so that each item in the listbox has a DataContext linked to that listbox Itemsource?

2

2 Answers

4
votes

You already know the answer: simply remove <UserControl.DataContext> from your UserControl

You are telling your UserControl to use a new instance of CatelogueModel for the DataContext, and this overrides any DataContext that is set when you use your UserControl. See MSDN's list of Dependency Property Precedence for more info

I do not ever recommend setting the DataContext inside a UserControl. It goes against how WPF is meant to work by having separate UI and data layers, and is a problem for anyone trying to use your UserControl

As for your question about each item in the ListBox linking to the ItemsSource, DataTemplates simply tell WPF how to draw an object. The data behind the object still remains.

For example, your ListBox contains a list of Record objects, and your DataTemplate is telling the ListBox to draw each one of those records with CatelogueRowView. The actual data behind the CatelogRowView is still your data object from catelogueViewModel.Records

0
votes

lbCatalogues.ItemsSource = catalogueViewModel.Records; instead of this Simply bind ItemsSource of ListBox as ItemsSource="{Binding Records}" in xaml. I hope this will help.