1
votes

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>
2
if interested, the project is available on gitajr

2 Answers

1
votes

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>
0
votes

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>