WPF DataGrid binding to an Entity Framework with help of mvvm light

c# datagrid entity-framework-core mvvm-light wpf

Question

I'm having trouble to be able to bind DeviceListDataGrid to an entity (EF7). The datagrid is not showing any of the data contained by the source. I'm using mvvm-light toolkit.

Here's the xaml

<Window
    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" 
    mc:Ignorable="d"
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
    xmlns:viewModel="clr-namespace:FxEditorDatabaseStructure.ViewModel"
    xmlns:domain="clr-namespace:FxEditorDatabaseStructure.Core.Domain"
    x:Class="FxEditorDatabaseStructure.Views.DeviceDatabaseView"
    DataContext="{Binding Source={StaticResource Locator}, Path=DeviceDatabaseViewModel}"
    Title="MainWindow" Height="800" Width="500">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Loaded">
            <i:InvokeCommandAction Command="{Binding WindowLoadedCommand}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
    <Grid DataContext="{Binding Source={StaticResource Locator}}">
        <Grid.RowDefinitions>
            <RowDefinition Height="2*" />
            <RowDefinition Height="2*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <TabControl Grid.Column="0" 
                    Grid.Row="1" 
                    x:Name="TabPanel" 
                    HorizontalAlignment="Left" 
                    Margin="0,20,0,0" 
                    Grid.ColumnSpan="2" 
                    Width="492">
            <TabItem Header="Basic">
                <Grid>
                    <TextBox x:Name="ProductCode" HorizontalAlignment="Left" Height="21.96" Margin="10,20,0,0" TextWrapping="Wrap" Text="{Binding DeviceDatabaseViewModel.DeviceList/Name}" VerticalAlignment="Top" Width="90" />
                    <TextBox x:Name="Description" HorizontalAlignment="Left" Height="21.96" Margin="10,70,0,0" TextWrapping="Wrap" Text="{Binding DeviceDatabaseViewModel.DeviceList.Count, Mode=OneWay}" VerticalAlignment="Top" Width="90" />
                    <TextBox x:Name="Notes" Height="71.96" Margin="121.5,20,125,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top"/>
                </Grid>
            </TabItem>
            <TabItem Header="Advanced"></TabItem>
            <TabItem Header="Technical data"></TabItem>
        </TabControl>
        <Menu Grid.Column="0" Grid.Row="0" x:Name="menuPanel" HorizontalAlignment="Left" Margin="0,0,0,0" Grid.ColumnSpan="2" Width="492">
            <MenuItem Header="Add device"></MenuItem>
            <MenuItem Header="Import database"></MenuItem>
            <MenuItem Header="Export database"></MenuItem>
        </Menu>
        <TextBlock x:Name="ProductSpecifications" HorizontalAlignment="Left" Grid.Row="1" Grid.Column="0"
                   TextWrapping="Wrap" Text="Product specifications" VerticalAlignment="Top" FontSize="9.333"/>
        <DataGrid 
                  x:Name="DeviceListDataGrid" 
                  Margin="0,25,0,0"
                  Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2"
                  AutoGenerateColumns="False" 
                  EnableRowVirtualization="True" 
                  AlternatingRowBackground="LightBlue" 
                  AlternationCount="2" 
                  RowDetailsVisibilityMode="VisibleWhenSelected"
                  ItemsSource="{Binding Source={StaticResource Locator}, Path=DeviceDatabaseViewModel}">
            <DataGrid.Columns>
                <DataGridTextColumn x:Name="NameColumn" Header="Name" Width="200*" Binding="{Binding DeviceList/Name}"  />
                <DataGridTextColumn x:Name="DescriptionColumn" Header="Description" Width="200*" Binding="{Binding DeviceList/Description}"/>
                <DataGridTextColumn x:Name="ProductTypeColumn" Header="Supplier" Width="150*" Binding="{Binding DeviceList/Supplier}"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

The text-boxes ProductCode and Description are working fine with similar binding approaches. Does the datagrid require some sort of special binding? I'am unable to see what is missing..

Earlier I asked question similar to this one, but now I would like to use mvvm light's locator approach for the data binding. Here is the earlier question with working solution. Binding entity into WPF datagrid with EF 7 (core) and the source for that questions code. https://msdn.microsoft.com/en-us/data/jj574514.aspx

As a background information here's the WindowLoadedMethod:

private void WindowLoadedMethod()
{
    _context.Devices.Load();
    _devices = _context.Devices.GetLocal();
    RaisePropertyChanged(() => DeviceList);
}

I have implemented the GetLocal method mentioned here. I assume it's not interfering the binding.

and DeviceList method:

public ObservableCollection<Device> DeviceList
{
    get
    {
        return _devices;
    }
}

and beginning of the viewmodel

public class DeviceDatabaseViewModel : ViewModelBase
{
    private IUnitOfWork _context = ServiceLocator.Current.GetInstance<IUnitOfWork>();
    private ObservableCollection<Device> _devices;
    public DeviceDatabaseViewModel()
    {
        WindowLoadedCommand = new RelayCommand(WindowLoadedMethod);
    }

    public RelayCommand WindowLoadedCommand { private set; get; }

and here the App.xaml

<Application x:Class="FxEditorDatabaseStructure.App" 
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
             xmlns:local="clr-namespace:FxEditorDatabaseStructure" 
             StartupUri="Views/MainWindow.xaml" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             d1p1:Ignorable="d"
             xmlns:d1p1="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:viewModel="clr-namespace:FxEditorDatabaseStructure.ViewModel">
  <Application.Resources>
    <ResourceDictionary>
            <viewModel:ViewModelLocator x:Key="Locator" d:IsDataSource="True" xmlns:vm="clr-namespace:FxEditorDatabaseStructure.ViewModel" />
    </ResourceDictionary>
  </Application.Resources>
</Application>
1
1
5/23/2017 12:15:41 PM

Accepted Answer

Solution:

<DataGrid 
          x:Name="DeviceListDataGrid" 
          Margin="0,25,0,0"
          Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2"
          AutoGenerateColumns="False" 
          EnableRowVirtualization="True" 
          AlternatingRowBackground="LightBlue" 
          AlternationCount="2" 
          RowDetailsVisibilityMode="VisibleWhenSelected"
          ItemsSource="{Binding DeviceDatabaseViewModel.DeviceList}">
    <DataGrid.Columns>
        <DataGridTextColumn x:Name="NameColumn" Header="Name" Width="200*" Binding="{Binding Name}"  />
        <DataGridTextColumn x:Name="DescriptionColumn" Header="Description" Width="200*" Binding="{Binding Description}"/>
        <DataGridTextColumn x:Name="Time" Header="Supplier" Width="150*" Binding="{Binding TimeCreated}"/>
    </DataGrid.Columns>
</DataGrid>

EDIT:

Changed the binding approach, now on code behind DeviceDatabaseView.xaml.cs

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    _context.Suppliers.Load();
    _context.Categories.Load();
    _context.Devices.Load();
    var devices = _context.Devices.GetLocal();
    DeviceListDataGrid.ItemsSource = devices;

    ICollectionViewLiveShaping deviceView =
        (ICollectionViewLiveShaping) CollectionViewSource.GetDefaultView(devices);
    deviceView.IsLiveSorting = true;
    ProductCategoryComboBox.ItemsSource = (System.Collections.IEnumerable) deviceView;

    SupplierComboBox.ItemsSource = _context.Suppliers.GetLocal();

}

and then on xaml:

<DataGrid 
          x:Name="DeviceListDataGrid" 
          Margin="0,25,0,0"
          Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="6"
          AutoGenerateColumns="False" 
          EnableRowVirtualization="True" 
          AlternatingRowBackground="LightBlue" 
          AlternationCount="2" 
          RowDetailsVisibilityMode="VisibleWhenSelected"
          SelectedItem="{Binding DeviceDatabaseViewModel.SelectedDevice}">
    <DataGrid.Resources>
        <SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="DarkCyan"/>
        <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="DarkCyan"/>
    </DataGrid.Resources>
    <DataGrid.Columns>
        <DataGridTextColumn x:Name="DeviceName" Header="Name" Width="200*" Binding="{Binding Name}"  />
        <DataGridTextColumn x:Name="DeviceDescriptionColumn" Header="Description" Width="200*" Binding="{Binding Description, Mode=TwoWay}"/>
        <DataGridTextColumn x:Name="DeviceSupplier" Header="Supplier" Width="150*" Binding="{Binding Supplier}"/>
        <DataGridTextColumn x:Name="DeviceCategory" Header="Category" Width="150*" Binding="{Binding Category}"/>
    </DataGrid.Columns>
</DataGrid>
0
2/26/2016 8:11:53 AM

Popular Answer

The problem is with the Binding of the columns. Just remove the "DiviceList/" from the binding. below is an example.

<DataGrid ItemsSource="{Binding MainMarkingList}" HorizontalAlignment="Center" VerticalAlignment="Top" AlternatingRowBackground="Gainsboro" AlternationCount="2" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Schedule" Binding="{Binding Schedule}"/>
                <DataGridTextColumn Header="Item" Binding="{Binding Item}"/>
                <DataGridTextColumn Header="Quantity" Binding="{Binding Qty}"/>
                <DataGridTextColumn Header="NP/Unit" Binding="{Binding NPUnit}"/>
                <DataGridTextColumn Header="First Var" Binding="{Binding FirstVarText}"/>
                <DataGridTextColumn Header="Second Var" Binding="{Binding SecondVarText}"/>
                <DataGridTextColumn Header="Third Var" Binding="{Binding ThirdVarText}"/>
                <DataGridTextColumn Header="Fourth Var" Binding="{Binding FourthVarText}"/>
                <DataGridTextColumn Header="Material" Binding="{Binding Material}"/>
                <DataGridTextColumn Header="Tag Size" Binding="{Binding TagSize}"/>
            </DataGrid.Columns>
        </DataGrid>


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow