Answered Multiple children to parent viewmodel binding

  • Wednesday, May 23, 2012 1:24 PM
     
      Has Code

    I am using entity type configuration to map to a DB that I cannot control. My parent object is a "user" based object which  has multiple one to many children entities to describe what each user is doing. The base model looks like this:

    Imports System.ComponentModel.DataAnnotations
    Imports System.Collections.ObjectModel
    Public Class MappingRecord
        Implements IValidatableObject
    #Region "properties"
        Public Property AppUserID() As String
        Public Property ReliefID() As Int32
        Public Overridable Property Clients() As ObservableCollection(Of ClientMapping)
        Public Overridable Property ServiceLines() As ObservableCollection(Of ServiceLineMapping)
        Public Overridable Property Capabilities() As ObservableCollection(Of CapabilityMapping)
        Public Overridable Property Assignments() As ObservableCollection(Of AssignmentMapping)
    #End Region
    ' ---- cut
    End Class

    To read from the DB I created a repository object that can read all the records for a user at once and load this model object.

        Public Function GetUserMappingRecord(userid As String) As MappingRecord Implements IMappingRepository.GetUserMappingRecord
            Dim results = From x In _context.MappingRecordList.Include("ServiceLines") _
                    .Include("Capabilities") _
                    .Include("Clients") _
                    .Include("Assignments")
            Where (x.AppUserID = userid)
            Select x
            Return results.FirstOrDefault
        End Function

    This works fine but to better manage all the validation for the children records I have started to switch from just referencing an observable collection of each child object found in the base model (Clients, ServiceLines, Capabilities, Assignments), to a viewmodel for every "row" I would see in a view. The validation isn't overy complex but it lends itself to this approach. For example, each client (or service line, or capability, or assignment) record has an allocation value that can be 0-100, and the collection of those must total 100. The viewmodel for each child (client) and then for the collection of the children (client_collection) works well and does what I want.

    My issue is trying to use my existing model to load my new view models. My main viewmodel reads the data from the repository via the MappingRecord object which has the observable collection for the children records. I used to bind datagrids to each of those observable collections but now I want to load them into new viewmodels (ClientMappingViewModel) that are collections of viewmodels (ClientMappingCollectionViewModel). I can load the records from my parent MappingRecord object by doing something like this

    Public Property UserMappingRecord As MappingRecord
    Public Property ClientMappingList As ClientMappingCollectionViewModel
    ClientMappingList = New ClientMappingCollectionViewModel(_mappingRepository, UserMappingRecord.Clients)

    But this doesn't provide a link to the original UserMappingRecord.Clients from the repository/context. So records that are added to the datagrid are not found in the MappingRecord and will not be subject to changes I've made to IValidatableObject.Validate.

    The easy solution is to not load the MappingRecord object and instead load each collection of children separately but then I lose any work done with Validate logic. I think I'm missing something basic but I'm just not seeing it right now. I want the view to reference the new viewmodels I've created like ClientMappingCollectionViewModel but I also want to use the MappingRecord model to load the data into the new viewmodels so that I can get the validation logic built into both.

All Replies

  • Thursday, May 24, 2012 2:16 PM
     
      Has Code

    To put this another way which might add more clarity, my datagrid binding handles updates to existing records but not adds and deletes. Here is a quick code sample showing snips of the relevant code.

    'top level viewmodel bound to view
    Public Class MappingRecordViewModel
        'collection of client mapping view models
        Public Property ClientMappingList As ClientMappingCollectionViewModel
        'load mapping record from repository
        UserMappingRecord = _mappingRepository.GetUserMappingRecord(SelectedUser.ID)
        'load viewmodel collection with data from previous result
        ClientMappingList = New ClientMappingCollectionViewModel(_mappingRepository, UserMappingRecord.Clients)
    Public Class MappingRecord
        'client mapping records in the MappingRecordClass
        Public Overridable Property Clients() As ObservableCollection(Of ClientMapping)
    Public Class ClientMappingViewModel
        'client mapping view model
        Public Property ClientMappingRecord As ClientMapping
    Public Class ClientMappingCollectionViewModel
        'collection of client mapping view models
        Public Property ClientMappingCollection As ObservableCollection(Of ClientMappingViewModel)

    On the view the datagrid is bound to ClientMappingList.

    I am not sure why updates to a row in the datagrid are reflected in both UserMappingRecord.Clients and ClientMappingList, yet adds and deletes are not. I think this is the root issue that I need clarity on.

  • Friday, May 25, 2012 7:25 AM
    Moderator
     
     

    Hi Pretzelb,

    it is hard to find the root cause of your issue, could you code a samll sample with me to demonstrate "adds and deletes" issue, and then I will do my best to help you resolve it.

    Best regards,


    Sheldon _Xiao[MSFT]
    MSDN Community Support | Feedback to us
    Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

  • Friday, May 25, 2012 3:29 PM
     
      Has Code

    I was afraid I had included too much code. Can you guide me on what else you might need?

    I did manage to get a sample working against an EDMX Northwind model. This uses objectcontext instead of dbcontext but shows similar behavior. Updating order_detail records on the grid will save to the DB but new rows or deleted rows are not registered.

    This is going to be a lot of code. I will try to limit it without causing confusion.

    Imports NorthwindData
    Class Application
        Private Sub Application_Startup(sender As Object, e As System.Windows.StartupEventArgs) Handles Me.Startup
            Dim view As New MainView
            Dim db As New NorthwindContext
            Dim rep As New NorthwindRepository(db)
            Dim vm As New MainViewModel(rep)
            view.DataContext = vm
            view.Show()
        End Sub
    End Class

    <Window x:Class="MainView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainView" Height="432" Width="728">
        <Window.Resources>
            <CollectionViewSource x:Key="cvsOrders" Source="{Binding Path=OrderCollectionVM.OrderVM_List}"/>
        </Window.Resources>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="60" />
                <RowDefinition Height="300*" />
                <RowDefinition Height="300*" />
                <RowDefinition Height="60" />
            </Grid.RowDefinitions>
            <StackPanel Grid.Row="0" Margin="5,0,0,0" FlowDirection="LeftToRight" Orientation="Horizontal" VerticalAlignment="Top"  HorizontalAlignment="Left" >
                <TextBlock Text="Select an order" Margin="5"></TextBlock>
                <ComboBox Height="28" Name="cmb1" Width="325" Margin="3"
                            IsEditable="False"
                            ItemsSource="{Binding Path=OrderCollectionVM.OrderVM_List,  Mode=OneWay,  UpdateSourceTrigger=PropertyChanged}"
                            SelectedItem="{Binding MySelectedOrder}">
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <StackPanel Orientation="Horizontal" >
                                <TextBlock Text="{Binding Path=CustomerID}" />
                                <TextBlock Text=" " />
                                <TextBlock Text="{Binding Path=ShipName}" />
                                <TextBlock Text=" " />
                                <TextBlock Text=" (" />
                                <TextBlock Text="{Binding Path=OrderID}" />
                                <TextBlock Text=") " />
                            </StackPanel>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ComboBox>
                <Button x:Name="btnSaveAll" 
                        Content="Save" 
                        Margin="30,5,5,5" 
                        Command="{Binding  SaveRecordCommand}" 
                        />
            </StackPanel>
            
            <StackPanel Grid.Row="1" Margin="5,0,0,0" FlowDirection="LeftToRight" Orientation="Horizontal" VerticalAlignment="Top"  HorizontalAlignment="Left" >
                <TextBlock Text="Product List" Margin="5"></TextBlock>
                <DataGrid x:Name="grd1" AutoGenerateColumns="False"                           
                                ItemsSource="{Binding MySelectedProducts.productVM_List, Mode=TwoWay, 
                                UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True, ValidatesOnDataErrors=True, 
                                ValidatesOnExceptions=True, NotifyOnValidationError=True}">
                    <DataGrid.Columns>
                        <DataGridTextColumn Width="75" 
                                                Header="ProductID"
                                                Binding="{Binding ProductID, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True, ValidatesOnDataErrors=True, 
                                                ValidatesOnExceptions=True, NotifyOnValidationError=True}" />
                        <DataGridTextColumn Width="150" 
                                                Header="ProductName"
                                                Binding="{Binding ProductName, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True, ValidatesOnDataErrors=True, 
                                                ValidatesOnExceptions=True, NotifyOnValidationError=True}" />
                        <DataGridTextColumn Width="100" 
                                                Header="UnitsOnOrder"
                                                Binding="{Binding UnitsOnOrder, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True, ValidatesOnDataErrors=True, 
                                                ValidatesOnExceptions=True, NotifyOnValidationError=True}" />
                    </DataGrid.Columns>
                </DataGrid>
            </StackPanel>
            <StackPanel Grid.Row="2" Margin="5,0,0,0" FlowDirection="LeftToRight" Orientation="Horizontal" VerticalAlignment="Top"  HorizontalAlignment="Left" >
                <TextBlock Text="Order Detail List" Margin="5"></TextBlock>
                <DataGrid x:Name="grd2" AutoGenerateColumns="False"                           
                                ItemsSource="{Binding MySelectedOrderDetails.OrderDetailVM_List, Mode=TwoWay, 
                                UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True, ValidatesOnDataErrors=True, 
                                ValidatesOnExceptions=True, NotifyOnValidationError=True}">
                    <DataGrid.Columns>
                        <DataGridTextColumn Width="75" 
                                                Header="OrderID"
                                                Binding="{Binding OrderID, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True, ValidatesOnDataErrors=True, 
                                                ValidatesOnExceptions=True, NotifyOnValidationError=True}" />
                        <DataGridTextColumn Width="150" 
                                                Header="ProductID"
                                                Binding="{Binding ProductID, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True, ValidatesOnDataErrors=True, 
                                                ValidatesOnExceptions=True, NotifyOnValidationError=True}" />
                        <DataGridTextColumn Width="100" 
                                                Header="Quantity"
                                                Binding="{Binding Quantity, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True, ValidatesOnDataErrors=True, 
                                                ValidatesOnExceptions=True, NotifyOnValidationError=True}" />
                        <DataGridTextColumn Width="100" 
                                                Header="UnitPrice"
                                                Binding="{Binding UnitPrice, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True, ValidatesOnDataErrors=True, 
                                                ValidatesOnExceptions=True, NotifyOnValidationError=True}" />
                        <DataGridTextColumn Width="100" 
                                                Header="Discount"
                                                Binding="{Binding Discount, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True, ValidatesOnDataErrors=True, 
                                                ValidatesOnExceptions=True, NotifyOnValidationError=True}" />
                    </DataGrid.Columns>
                </DataGrid>
            </StackPanel>
            
            <StackPanel Grid.Row="3" Margin="5,0,0,0" FlowDirection="LeftToRight" Orientation="Horizontal" VerticalAlignment="Top"  HorizontalAlignment="Left" >
                <TextBlock Text="Messages" Margin="5"></TextBlock>
                <TextBlock Text="{Binding Messages,  UpdateSourceTrigger=PropertyChanged}" />
            </StackPanel>
        </Grid>
    </Window>

    Imports System.Collections.ObjectModel
    Imports System.ComponentModel
    Imports NorthwindData
    Public Class MainViewModel
        Implements INotifyPropertyChanged
    #Region "declarations"
        Private Property _repository As NorthwindRepository
        Private Property _ordercollvm As OrderCollectionViewModel
        Private Property _myselectedorder As OrderViewModel
        Private Property _myselectedproducts As ProductCollectionViewModel
        Private Property _myselectedorderdetails As OrderDetailCollectionViewModel
        Private _savecommand As RelayCommand
        Private _errorlist As New Dictionary(Of String, String)
    #End Region
    #Region "constructors"
        Public Sub New(ByVal rep As NorthwindRepository)
            _repository = rep
            OrderCollectionVM = New OrderCollectionViewModel(_repository)
        End Sub
    #End Region
    #Region "properties"
        Public ReadOnly Property Messages As String
            Get
                Dim msg As String = ""
                For Each x In _errorlist
                    msg = msg & x.Key & " " & x.Value
                Next
                Return msg
            End Get
        End Property
        Public Property ErrorList As Dictionary(Of String, String)
            Get
                Return _errorlist
            End Get
            Set(value As Dictionary(Of String, String))
                _errorlist = value
                OnPropertyChanged("ErrorList")
                OnPropertyChanged("Messages")
            End Set
        End Property
        Public Property OrderCollectionVM As OrderCollectionViewModel
            Get
                Return _ordercollvm
            End Get
            Set(value As OrderCollectionViewModel)
                _ordercollvm = value
                OnPropertyChanged("OrderCollectionVM")
            End Set
        End Property
        Public Property MySelectedOrder As OrderViewModel
            Get
                Return _myselectedorder
            End Get
            Set(value As OrderViewModel)
                _myselectedorder = value
                OnPropertyChanged("MySelectedOrder")
                MySelectedProducts = New ProductCollectionViewModel(_repository, MySelectedOrder.OrderProducts)
                MySelectedOrderDetails = New OrderDetailCollectionViewModel(_repository, MySelectedOrder.Order_Details)
            End Set
        End Property
        Public Property MySelectedProducts As ProductCollectionViewModel
            Get
                Return _myselectedproducts
            End Get
            Set(value As ProductCollectionViewModel)
                _myselectedproducts = value
                OnPropertyChanged("MySelectedProducts")
            End Set
        End Property
        Public Property MySelectedOrderDetails As OrderDetailCollectionViewModel
            Get
                Return _myselectedorderdetails
            End Get
            Set(value As OrderDetailCollectionViewModel)
                _myselectedorderdetails = value
                OnPropertyChanged("MySelectedOrderDetails")
            End Set
        End Property
        Public ReadOnly Property CanSave
            Get
                Return True
            End Get
        End Property
    #End Region
    #Region "methods"
        Public ReadOnly Property SaveRecordCommand() As ICommand
            Get
                If _savecommand Is Nothing Then
                    Dim btnaction As New Action(Of Object)(AddressOf Me.SaveRecord)
                    _savecommand = New RelayCommand(btnaction, Function(x) Me.CanSave)
                End If
                Return _savecommand
            End Get
        End Property
        Public Sub SaveRecord()
            Try
                Dim iret As Integer = 0
                ErrorList.Clear()
                iret = _repository.SaveChanges()
                Select Case iret
                    Case -1
                        ErrorList = _repository.ErrorList
                    Case 0
                        ErrorList.Add("Alert ", "No changes found")
                    Case Else
                        ErrorList.Add("Success ", CStr(iret) & " changes saved")
                End Select
                If iret = -1 Then
                Else
                    OnPropertyChanged("MainViewModel")
                End If
            Catch ex As Exception
                ErrorList.Add("View Model Error", ex.Message)
                If Not IsNothing(_repository.ErrorList) Then
                    ErrorList = _repository.ErrorList
                End If
            Finally
                OnPropertyChanged("Messages")
            End Try
        End Sub
    #End Region
    #Region "INotifyPropertyChanged Members"
        ''' <summary>
        ''' Raised when a property on this object has a new value.
        ''' </summary>
        Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
        ''' <summary>
        ''' Raises this object's PropertyChanged event.
        ''' </summary>
        ''' <param name="propertyName">The property that has a new value.</param>
        Protected Overridable Sub OnPropertyChanged(ByVal propertyName As String)
            Dim handler As PropertyChangedEventHandler = Me.PropertyChangedEvent
            If handler IsNot Nothing Then
                Dim e = New PropertyChangedEventArgs(propertyName)
                handler(Me, e)
            End If
        End Sub
    #End Region ' INotifyPropertyChanged Members
    End Class

    Imports System.Collections.ObjectModel
    Imports System.ComponentModel
    Imports NorthwindData
    Imports System.Data.Objects
    Imports System.Data.Objects.DataClasses
    Public Class OrderDetailCollectionViewModel
        Implements INotifyPropertyChanged
        Private Property _repository As NorthwindRepository
        Private Property _orderdetailvm_list As ObservableCollection(Of OrderDetailViewModel)
        Public Sub New(ByVal rep As NorthwindRepository)
            _repository = rep
            _orderdetailvm_list = New ObservableCollection(Of OrderDetailViewModel)
        End Sub
        Public Sub New(ByVal rep As NorthwindRepository, ByVal objlist As ObservableCollection(Of Order_Detail))
            _repository = rep
            _orderdetailvm_list = New ObservableCollection(Of OrderDetailViewModel)
            For Each obj In objlist
                _orderdetailvm_list.Add(New OrderDetailViewModel(rep, obj))
            Next
        End Sub
        Public Sub New(ByVal rep As NorthwindRepository, ByVal objlist As EntityCollection(Of Order_Detail))
            _repository = rep
            _orderdetailvm_list = New ObservableCollection(Of OrderDetailViewModel)
            For Each obj In objlist
                _orderdetailvm_list.Add(New OrderDetailViewModel(rep, obj))
            Next
        End Sub
        Public Property OrderDetailVM_List As ObservableCollection(Of OrderDetailViewModel)
            Get
                Return _orderdetailvm_list
            End Get
            Set(value As ObservableCollection(Of OrderDetailViewModel))
                _orderdetailvm_list = value
                OnPropertyChanged("OrderDetailVM_List")
            End Set
        End Property
    #Region "INotifyPropertyChanged Members"
        ''' <summary>
        ''' Raised when a property on this object has a new value.
        ''' </summary>
        Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
        ''' <summary>
        ''' Raises this object's PropertyChanged event.
        ''' </summary>
        ''' <param name="propertyName">The property that has a new value.</param>
        Protected Overridable Sub OnPropertyChanged(ByVal propertyName As String)
            Dim handler As PropertyChangedEventHandler = Me.PropertyChangedEvent
            If handler IsNot Nothing Then
                Dim e = New PropertyChangedEventArgs(propertyName)
                handler(Me, e)
            End If
        End Sub
    #End Region ' INotifyPropertyChanged Members
    End Class

    Imports System.Collections.ObjectModel
    Imports System.ComponentModel
    Imports NorthwindData
    Public Class OrderDetailViewModel
        Implements INotifyPropertyChanged
        Private Property _repository As NorthwindRepository
        Private Property _order_detail As Order_Detail
        Public Sub New(ByVal rep As NorthwindRepository, ByVal orderid As Integer, ByVal prodid As Integer)
            _repository = rep
            order_detail = rep.SelectOrderDetailByOrderIdandProductId(orderid, prodid)
        End Sub
        Public Sub New(ByVal rep As NorthwindRepository, ByVal obj As order_detail)
            _repository = rep
            Order_Detail = obj
        End Sub
        Public Sub New()
            _order_detail = New Order_Detail()
            _order_detail.OrderID = 0
            _order_detail.ProductID = 0
            _order_detail.Quantity = 0
            _order_detail.UnitPrice = 0
            _order_detail.Discount = 0
        End Sub
        Public Sub New(ByVal orderid As Integer, ByVal prodid As Integer, ByVal quantity As Integer, ByVal up As Decimal, ByVal dis As Single)
            _order_detail = New Order_Detail()
            _order_detail.OrderID = orderid
            _order_detail.ProductID = prodid
            _order_detail.Quantity = quantity
            _order_detail.UnitPrice = up
            _order_detail.Discount = dis
        End Sub
        Public Property Order_Detail As Order_Detail
            Get
                Return _order_detail
            End Get
            Set(value As Order_Detail)
                _order_detail = value
                OnPropertyChanged("order_detail")
            End Set
        End Property
        Public Property OrderID As Integer
            Get
                Return order_detail.OrderID
            End Get
            Set(value As Integer)
                order_detail.OrderID = value
                OnPropertyChanged("OrderID")
            End Set
        End Property
        Public Property ProductID As Integer
            Get
                Return order_detail.ProductID
            End Get
            Set(value As Integer)
                order_detail.ProductID = value
                OnPropertyChanged("ProductID")
            End Set
        End Property
        Public Property Quantity As Integer
            Get
                Return order_detail.Quantity
            End Get
            Set(value As Integer)
                order_detail.Quantity = value
                OnPropertyChanged("Quantity")
            End Set
        End Property
        Public Property UnitPrice() As Global.System.Decimal
            Get
                Return Order_Detail.UnitPrice
            End Get
            Set(value As Global.System.Decimal)
                Order_Detail.UnitPrice = value
                OnPropertyChanged("UnitPrice")
            End Set
        End Property
        Public Property Discount() As Global.System.Single
            Get
                Return Order_Detail.Discount
            End Get
            Set(value As Global.System.Single)
                Order_Detail.Discount = value
                OnPropertyChanged("Discount")
            End Set
        End Property
        Public ReadOnly Property ProductName As String
            Get
                Return Order_Detail.Product.ProductName
            End Get
        End Property
    #Region "INotifyPropertyChanged Members"
        ''' <summary>
        ''' Raised when a property on this object has a new value.
        ''' </summary>
        Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
        ''' <summary>
        ''' Raises this object's PropertyChanged event.
        ''' </summary>
        ''' <param name="propertyName">The property that has a new value.</param>
        Protected Overridable Sub OnPropertyChanged(ByVal propertyName As String)
            Dim handler As PropertyChangedEventHandler = Me.PropertyChangedEvent
            If handler IsNot Nothing Then
                Dim e = New PropertyChangedEventArgs(propertyName)
                handler(Me, e)
            End If
        End Sub
    #End Region ' INotifyPropertyChanged Members
    End Class

    Imports System
    Imports System.Data.Objects
    Imports NorthwindData.NorthwindModel
    Imports System.Collections.ObjectModel
    Public Class NorthwindContext
        Inherits ObjectContext
        Public Property Categories As ObjectSet(Of Category)
        Public Property Products() As ObjectSet(Of Product)
        Public Property Customers() As ObjectSet(Of Customer)
        Public Property Orders As ObjectSet(Of Order)
        Public Property Order_Details As ObjectSet(Of Order_Detail)
        Public Sub New()
            MyBase.New("name=NorthwindEntities", "NorthwindEntities")
            Categories = CreateObjectSet(Of Category)()
            Products = CreateObjectSet(Of Product)()
            Customers = CreateObjectSet(Of Customer)()
            Orders = CreateObjectSet(Of Order)()
            Order_Details = CreateObjectSet(Of Order_Detail)()
        End Sub
    End Class

    Imports System.Collections.ObjectModel
    Imports System.Data.Entity.Validation
    Public Class NorthwindRepository
        Private Property _context As NorthwindContext
        Private Property _errors As New Dictionary(Of String, String)
        Public Sub New(ByVal context As NorthwindContext)
            _context = context
        End Sub
        Public Property ErrorList As Dictionary(Of String, String)
            Get
                Return _errors
            End Get
            Set(value As Dictionary(Of String, String))
                _errors = value
            End Set
        End Property
        Public Function SelectOrderDetailByOrderId(ByVal orderid As Integer) As ObservableCollection(Of Order_Detail)
            Dim results = From x In _context.Order_Details.Include("Product").Include("Order").Include("Product.Category")
                  Where x.OrderID = orderid
                  Select x
            Return New ObservableCollection(Of Order_Detail)(results)
        End Function
        Public Function SelectProductById(ByVal id As Integer) As Product
            Dim results = From x In _context.Products
                  Where x.ProductID = id
                  Select x
            Return results.FirstOrDefault
        End Function
        Public Function SelectOrderById(ByVal orderid As Integer) As Order
            Dim results = From x In _context.Orders
                  Where x.OrderID = orderid
                  Select x
            Return results.FirstOrDefault
        End Function
        Public Function SelectOrderById_inclusive(ByVal orderid As Integer) As Order
            Dim results = From x In _context.Orders.Include("Order_Details")
                  Where x.OrderID = orderid
                  Select x
            Return results.FirstOrDefault
        End Function
        Public Function SelectOrderDetailByOrderIdandProductId(ByVal orderid As Integer, ByVal prodid As Integer) As Order_Detail
            Dim results = From x In _context.Order_Details.Include("Product").Include("Order").Include("Product.Category")
                  Where x.OrderID = orderid AndAlso x.ProductID = prodid
                  Select x
            Return results.FirstOrDefault
        End Function
        Public Function SelectAllOrder() As ObservableCollection(Of Order)
            Dim results = From x In _context.Orders
                          Select x
            Return New ObservableCollection(Of Order)(results)
        End Function
        Public Function SelectAllProduct() As ObservableCollection(Of Product)
            Dim results = From x In _context.Products
                          Select x
            Return New ObservableCollection(Of Product)(results)
        End Function
        Public Function SelectProductByCategory(ByVal catid As Integer) As ObservableCollection(Of Product)
            Dim results = From x In _context.Products
                          Where x.CategoryID = catid
                          Select x
            Return New ObservableCollection(Of Product)(results)
        End Function
        Public Function SelectProductByOrderID(ByVal orderid As Integer) As ObservableCollection(Of Product)
            Dim results = (From p In _context.Products
                                          From o In _context.Orders
                                          From od In _context.Order_Details
                                          Where o.OrderID = od.OrderID AndAlso od.ProductID = p.ProductID AndAlso o.OrderID = orderid
                                          Select p)
            Return New ObservableCollection(Of Product)(results)
        End Function
        Public Function SelectAllCategory() As ObservableCollection(Of Category)
            Dim results = From x In _context.Categories
                          Select x
            Return New ObservableCollection(Of Category)(results)
        End Function
        Public Function SaveChanges() As Integer
            Dim inumchanges As Integer = 0
            Try
                inumchanges = _context.SaveChanges
            Catch ex As Exception
                inumchanges = -1
                Dim results As New Dictionary(Of String, String)
                results.Add("Unexpected Error", ex.Message)
                If Not IsNothing(ex.InnerException) Then
                    Dim innermsg As String = ""
                    If ex.Message = ex.InnerException.Message Then
                        innermsg = ex.InnerException.InnerException.Message
                    Else
                        innermsg = ex.InnerException.Message
                    End If
                    results.Add("Unexpected Error", innermsg)
                End If
                _errors = results
            End Try
            Return inumchanges
        End Function
    End Class

    • Edited by pretzelb Friday, May 25, 2012 6:43 PM added code sample
    •  
  • Wednesday, May 30, 2012 6:06 AM
    Moderator
     
     

    Hi pretzelb,

    I am working on your issue, I will follow up your issue later.

    best regards,


    Sheldon _Xiao[MSFT]
    MSDN Community Support | Feedback to us
    Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

  • Monday, June 04, 2012 10:23 PM
     
     

    Sheldon

    I uploaded a demo project to skydrive to try and show the issue. The demo attempts to keep it simple with basic objects like Employees, Product Lines, and Clients. But it does get involved with this simple model. It also includes initialization to create test data.

    In the demo the grid on the left binds to an observable collection of entities via a CollectionViewSource. This left grid works fine. Add, update, and delete all function.

    The grid on the right bings to a view model that is a collection of other view models. The Client Allocation entity is loaded into a Client Allocation view model and a collection of those are loaded into the Client Allocation Collection view model. The grid on the right binds to this collection view model but add and deletes are not transmitted to the underlying EmpDetailMaster entity.

    Hopefully this helps.

  • Monday, June 11, 2012 5:08 AM
     
     

    You might look at MVVM approach http://blogs.msdn.com/b/ivo_manolov/archive/2012/03/17/10284665.aspx.


    Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.

    Regards,
    Jacky Wu
    Microsoft Online Community Support

  • Tuesday, June 12, 2012 2:24 PM
     
     

    You might look at MVVM approach http://blogs.msdn.com/b/ivo_manolov/archive/2012/03/17/10284665.aspx.


    Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.

    Regards,
    Jacky Wu
    Microsoft Online Community Support


    I am using MVVM.
  • Tuesday, June 12, 2012 2:40 PM
     
     Answered

    I am still not sure what is common out there for others but I've decided that if I want to use MVVM in such a way that each entity has it's own view model and a collection of view models is also represented by a view model, then I need to generate the support structure to fix the links broken by copying from the context to the view model. For example, a delete on a child record like ClientMapping needs to trigger an event to communicate not only to the collection of of ClientMapping records in the view model, but also to the MappingRecord entity which then needs to update it's collection under the Clients() property (which is linked to the context).

    • Marked As Answer by pretzelb Tuesday, June 12, 2012 2:40 PM
    •  
  • Wednesday, June 13, 2012 9:39 AM
    Moderator
     
     

    Hi Pretzelb,

    Sorry for interup. The following information is not related to this thread and it is about another thread.

    It seems Sheldon moved your thread http://social.msdn.microsoft.com/Forums/en-US/adonetefx/thread/2b21df9c-e55f-40b8-9c66-573dc68ee95a to an achieved forum by mistake. That forum is locked and cannot be replied.

    That question will have better support in EF forum http://social.msdn.microsoft.com/Forums/en/adodotnetentityframework/threads.

    Could you please re-post that question in EF forum? Our data guy will help you there.

    Thanks for your understanding and support!

    Best regards,


    Min Zhu [MSFT]
    MSDN Community Support | Feedback to us