Nekeniehl
Nekeniehl

Reputation: 1691

DataGrid on UserControl doesn't display binded ObservableCollection

I have a MainWindow with some buttons that loads a collection:

<Window x:Class="GUI.MainWindow.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:mainWindowViewModel="clr-namespace:GUI.MainWindow"
        xmlns:s="clr-namespace:Helpers"
        xmlns:configuration="clr-namespace:GUI.Configuration"
        xmlns:results="clr-namespace:GUI.Results"
        mc:Ignorable="d"
        Title="{Binding Path=Model.Title}"
        Width="Auto"
        WindowStartupLocation="CenterScreen">

    <Window.Resources>
        <DataTemplate DataType="{x:Type results:ResultViewModel}">
             <results:ResultView/>
        </DataTemplate>
    </Window.Resources>

    <!--DataContext-->
    <Window.DataContext>
        <mainWindowViewModel:MainWindowViewModel />
    </Window.DataContext>
    <!--DataContext-->

    <!--Main Grid-->
    <Grid Name="MainGrid"
          Margin="5"
          HorizontalAlignment="Stretch"
          VerticalAlignment="Stretch">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="8*" />
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <!--Tabs-->
        <TabControl Grid.Row="1"
                    Grid.RowSpan="2"
                    Grid.Column="0"
                    VerticalAlignment="Stretch">

            <!--Result View-->
            <TabItem Header="{Binding Model.TabImportHeader}">
                <ContentControl Content="{Binding ResultViewModel}"/>
            </TabItem>
        </TabControl>
        <!--Tabs-->

        <!--Buttons-->
        <Grid Grid.Row="2">
            <Grid.ColumnDefinitions>
                <ColumnDefinition />
                <ColumnDefinition />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <Button Grid.Row="0"
                    Grid.Column="0"
                    Margin="10"
                    Height="25"
                    Width="150"
                    Content="Load"
                    Command="{Binding LoadCommand}" />
            <Button Grid.Row="0"
                    Grid.Column="2"
                    Margin="10"
                    Height="25"
                    Width="150"
                    Content="Reload"
                    Command="{Binding ReloadCommand}" />
        </Grid>
        <!--Buttons-->

    </Grid>
    <!--Main Grid-->
</Window>

Then I have a UserControl which should display the loaded collection, but shows nothing.

<UserControl x:Class="GUI.Results.ResultView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:GUI.Results"
             mc:Ignorable="d">

    <UserControl.DataContext>
        <local:ResultViewModel />
    </UserControl.DataContext>

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="87*" />
            <ColumnDefinition Width="415*" />
            <ColumnDefinition Width="501*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <DataGrid Grid.Column="0"
                              Grid.ColumnSpan="3"
                              Grid.Row="0"
                              ItemsSource="{Binding Model.Collections}"
                              ColumnWidth="*"
                              AutoGenerateColumns="false"
                              HorizontalAlignment="Stretch"
                              IsReadOnly="True">
            <DataGrid.Resources>
                <Style TargetType="DataGridColumnHeader">
                    <Setter Property="HorizontalContentAlignment"
                                        Value="Center" />
                </Style>
            </DataGrid.Resources>
            <DataGrid.Columns>
                <DataGridTextColumn Header="Filename"
                                                Binding="{Binding ResultInfo.Filename}"
                                                Width="Auto" />
                <DataGridTextColumn Header="Score 1"
                                                Binding="{Binding ResultInfo.Score1, StringFormat=F4, ConverterCulture=de-DE}"
                                                Width="Auto" />
                <DataGridTextColumn Header="Score 2"
                                                Binding="{Binding ResultInfo.Score2, StringFormat=F4, ConverterCulture=de-DE}"
                                                Width="Auto" />
                <DataGridTextColumn Header="Score 3"
                                                Binding="{Binding ResultInfo.Score3, StringFormat=F4, ConverterCulture=de-DE}"
                                                Width="Auto" />
                <DataGridTextColumn Header="Score 4"
                                                Binding="{Binding ResultInfo.Score4, StringFormat=F4, ConverterCulture=de-DE}"
                                                Width="Auto" />
                <DataGridTextColumn Header="SaMP"
                                                Binding="{Binding ResultInfo.SaMP}"
                                                Width="Auto" />
                <DataGridTextColumn Header="Spig"
                                                Binding="{Binding ResultInfo.Spig}"
                                                Width="Auto" />
                <DataGridTextColumn Header="Ppig"
                                                Binding="{Binding ResultInfo.Ppig, StringFormat=00.0##\\%}"
                                                Width="Auto" />
                <DataGridTextColumn Header="Pigment3"
                                                Binding="{Binding ResultInfo.Pigment3}"
                                                Width="Auto" />
                <DataGridTextColumn Header="Pigment4"
                                                Binding="{Binding ResultInfo.Pigment4}"
                                                Width="Auto" />
                <DataGridTextColumn Header="ZQ1"
                                                Binding="{Binding ResultInfo.ZQ1}"
                                                Width="Auto" />
                <DataGridTextColumn Header="ZQ2"
                                                Binding="{Binding ResultInfo.ZQ2}"
                                                Width="Auto" />
                <DataGridTextColumn Header="ZQ3"
                                                Binding="{Binding ResultInfo.ZQ3}"
                                                Width="Auto" />
                <DataGridTextColumn Header="ZQ4"
                                                Binding="{Binding ResultInfo.ZQ4}"
                                                Width="Auto" />
                <DataGridTextColumn Header="Message"
                                                Binding="{Binding ResultInfo.Message}"
                                                Width="Auto" />
                <DataGridTextColumn Header="Distance"
                                                Binding="{Binding ResultInfo.PowDistance, StringFormat=F2, ConverterCulture=de-DE}"
                                                Width="Auto" />
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</UserControl>

Here how I put the data inside the collection (values are there if I debug):

Application.Current.Dispatcher.Invoke(() => MainWindowViewModel.ResultViewModel.Model.Collections.Add(Collection));

Collections is type of ObservableCollection<>;

Seems that I'm missing something in the binding but I'm quite new to WPF and MVVM and I don't find it. I have read about DependencyProperty but I would like to have a ViewModel for my userControl as it will get eventually more complex.

I will really appreciate any help.

Upvotes: 0

Views: 60

Answers (1)

Clemens
Clemens

Reputation: 128061

You have two instances of ResultViewModel, one in the MainWindowViewModel.ResultViewModel property, the other directly assigned to the UserControl's DataContext:

<UserControl.DataContext>
    <local:ResultViewModel />
</UserControl.DataContext>

Remove the above from the UserControl's XAML.

In general, a UserControl should never have its "own" view model, and you should never explicitly set its DataContext property in its XAML or code behind. Doing so overrides the value of the inherited DataContext, which contains the correct ResultViewModel instance.

Upvotes: 1

Related Questions