CRUD Operation using QSDCV and MVVM-Light

4 posts, 1 answers
  1. Azib
    Azib avatar
    7 posts
    Member since:
    Jun 2012

    Posted 15 Jun 2012 Link to this post

    I am trying to use QSDCV for my Sales Order Page to perform a CRUD, but seems like not getting there! here is what i am doing.

    Model : 
    • I have Sales Order Entity called SOPDoc
    • I have a Child Entity to SOPDoc, called SOPDocDetails. This holds all the items for a specific Order and can be accessed like SOPDoc.SOPDocDetails which returns IEnumerable<SOPDocDetails>. I am using OpenAccess for Model.

    ViewModel :
    •  QueryableDomainServiceCollectionView for SOPDoc, which loads a single record.
      public const string qsdcvSOPDocPropertyName = "qsdcvSOPDoc";
      private QueryableDomainServiceCollectionView<SOPDoc> _qsdcvSOPDoc;
      public QueryableDomainServiceCollectionView<SOPDoc> qsdcvSOPDoc
           {
               get
               {
                   return _qsdcvSOPDoc;
               }
               set
               {
                   if (_qsdcvSOPDoc == value)
                   {
                       return;
                   }
                   var oldValue = _qsdcvSOPDoc;
                   _qsdcvSOPDoc = value;
                   RaisePropertyChanged(qsdcvSOPDocPropertyName, oldValue, value, true);
               }
           }

    • Current Sales Order ID, this holds the ID of current sales order and is used while loading QSDCV
      public const string CurrentSalesOrderIdPropertyName = "CurrentSalesOrderId";
      private int _currentSalesOrderId;
      public int CurrentSalesOrderId
              {
                  get
                  {
                      return _currentSalesOrderId;
                  }
                  set
                  {
                      if (_currentSalesOrderId == value)
                      {
                          return;
                      }
                      var oldValue = _currentSalesOrderId;
                      _currentSalesOrderId = value;
                      RaisePropertyChanged(CurrentSalesOrderIdPropertyName, oldValue, value, true);
                  }
              }

    • Current Order Entity, When QSDCV Loaded Event Fires, from the result, FirstOrDefault() is populated to 'entCurrentOrder'. This is then used to bind different View Controls, e.g. Order Date, Ordering Customer, Discount Amount or Carriage etc.

    • public
       const string entCurrentOrderPropertyName = "entCurrentOrder";
      private SOPDoc _entCurrentOrder;
       public SOPDoc entCurrentOrder
              {
                  get
                  {
                      return _entCurrentOrder;
                  }
                  set
                  {
                      if (_entCurrentOrder == value)
                      {
                          return;
                      }
                      _entCurrentOrder = value;
                      RaisePropertyChanged(entCurrentOrderPropertyName);
                  }
              }

    • entSOPDocDetail is used as CurrentItem binding for the RadGridView & RadDataForm in the view.
      public const string entSOPDocDetailPropertyName = "entSOPDocDetail";
      private SOPDocDetail _entSOPDocDetail;
      public SOPDocDetail entSOPDocDetail
              {
                  get
                  {
                      return _entSOPDocDetail;
                  }
                  set
                  {
                      if (_entSOPDocDetail == value)
                      {
                          return;
                      }
                      var oldValue = _entSOPDocDetail;
                      _entSOPDocDetail = value;
                      RaisePropertyChanged(entSOPDocDetailPropertyName, oldValue, value, true);
                  }
              }

    • ViewModelConstructor
      public SalesOrderViewModel()
      {
         CurrentSalesOrderId = 1; // this is just for example while testing the page, so that it loads the SalesOrder with ID = 1
         ctx = new KERPDomainContext();
         qry = ctx.GetSalesOrderByIdQuery(CurrentSalesOrderId);
         qsdcvSOPDoc = new QueryableDomainServiceCollectionView<SOPDoc>(ctx, qry);
         qsdcvSOPDoc.Load();
         qsdcvSOPDoc.LoadedData += qsdcvSOPDoc_LoadedData;
      }

    • Loaded Event for QSDCV, here i bind entCurrentOrder to the returned entity and depending on the PageMode Value (this is another property which i set to establish a new order being saved or existing one to be pulled), i.e. 'New' or 'Edit'.
      void qsdcvSOPDoc_LoadedData(object sender, LoadedDataEventArgs e)
            {
                if (!e.HasError)
                {
                    entCurrentOrder = (SOPDoc) e.Entities.FirstOrDefault(); // Loads the Current Order in an Entity so that it can be boudn to the veiw controls
       
                    if (PageMode == Enums.SODModes.New.ToString() && CurrentSalesOrderId <= 0)
                    {
                        // Do something ......
                    }
                    if (PageMode == Enums.SODModes.Edit.ToString() && CurrentSalesOrderId > 0)
                    {
                        if (entCurrentOrder != null)
                        {
                            OrderingCustomer = entCurrentOrder.Customer; // assign current Customer to a <Customer> OrderingCustomer to be used in View databinding
                            GrossAmount = entCurrentOrder.SOPDocDetails.Sum(i => i.NetAmount);
                            Carriage = entCurrentOrder.Carriage;
                            Discount = entCurrentOrder.Discount;
                        }
                    }
                }
            }

    View : My View is of a Single Page for Editing and Updating
    • SalesOrderView.xaml, it is a silvelright page which holds multiple user controls, all binds to the SalesOrderViewModel.cs, one of the UserControl is SalesItems.xaml
    SalesOrder.xaml holds RadGridView and RadDataForm both bound to same ItemSource and Current Item in ViewModel as below
    <telerik:RadGridView  Grid.Row="1"  AutoExpandGroups="True" AutoGenerateColumns="False" ColumnWidth="*" CurrentItem="{Binding entSOPDocDetail}" IsSynchronizedWithCurrentItem="True" IsReadOnly="False" ItemsSource="{Binding rocTest}">
                   <telerik:RadGridView.Columns>
                       <telerik:GridViewDataColumn Header="Product Code" DataMemberBinding="{Binding ProductCode}" Width="1.5*"/>
                       <telerik:GridViewDataColumn Header="Description" DataMemberBinding="{Binding Description}" Width="5*"/>
                       <telerik:GridViewDataColumn Header="Qty" DataMemberBinding="{Binding Qty}" Width="*"/>
                       <telerik:GridViewDataColumn Header="UnitType" DataMemberBinding="{Binding UnitType}"/>
                       <telerik:GridViewDataColumn Header="Unit Price" DataMemberBinding="{Binding UnitPrice}" DataFormatString="{}{0:0,0.00}"/>
                       <telerik:GridViewDataColumn Header="Line Total" DataMemberBinding="{Binding NetAmount}" DataFormatString="{}{0:0,0.00}"/>
                       <telerik:GridViewColumn Width="90">
                           <telerik:GridViewColumn.CellTemplate>
                               <DataTemplate>
                                   <telerik:RadButton Content="Delete" Command="telerik:RadGridViewCommands.Delete" CommandParameter="{Binding}" />
                               </DataTemplate>
                           </telerik:GridViewColumn.CellTemplate>
                       </telerik:GridViewColumn>
                   </telerik:RadGridView.Columns>         
           </telerik:RadGridView>
      
      
    <telerik:RadDataForm x:Name="dataForm"
               CommandButtonsVisibility="Cancel,Commit"
               AutoGenerateFields="False"
               ValidationSummaryVisibility="Collapsed"
               EditEnded="RadDataForm_EditEnded"
               CurrentItemChanged="OnDataFormCurrentItemChanged"
               LabelPosition="Above"
               EditTemplate="{StaticResource SOItemsEditTemplate}"
               NewItemTemplate="{StaticResource SOItemsEditTemplate}"
               VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" CurrentItem="{Binding entSOPDocDetail}" ItemsSource="{Binding rocTest}" Margin="0,0,0,14" Grid.RowSpan="2" HorizontalAlignment="Left" Width="321"/>

    • In the same page SOPItems.xaml i have two buttons bound to RadDataForm 'Add' and 'Edit' Commands
      <telerik:RadButton  Tag="Add"   Command="telerik:RadDataFormCommands.AddNew" CommandTarget="{Binding ElementName=dataForm}" />
        
       <telerik:RadButton Tag="Edit" Command="telerik:RadDataFormCommands.BeginEdit" CommandTarget="{Binding ElementName=dataForm}" />


    PROBLEM :
    • When i bind RadDataForm's ItemSource property to IEnumerable<SOPDoc.SOPDocDetails>, the Edit and Add buttons are disabled. Also i cant seem to find out a way to set 'CurrentSalesOrderId' in usercontrol's Loaded event because the ViewModel Constructor is executed long before the execution of UserControl's Loaded Event.
    • How do i SaveChanges to QSDCV which includes changing the existing entity but if this is a new order, it saves a new entity.... i am totally lost by experimenting so many things so many times, i cant seems to grab the concept

    Please do not get put off by the length of the question, my question is very simple and it is just the concept i am after, all the code snippets are just to help you understand and please tell me if i am doing it wrong.

    Any Help will be HUGELY appreciated since even cant get help from StackOverFlow !!! question remained unanswered!! .... PLEASE HELP....thx


  2. Nedyalko Nikolov
    Admin
    Nedyalko Nikolov avatar
    871 posts

    Posted 19 Jun 2012 Link to this post

    Hi,

    You can take a look at this blog post for more info how to create CRUD operations using RadDomainDataSource.
    Now straight onto your questions:

    1. There is no way to edit or add an item into IEnumerable<T> collection, in order to enable editing you need at least IList<T>.
    2.You can call QDSCV.SubmitChanges() methos which will save the changes to the underlying database.

    All the best,
    Nedyalko Nikolov
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

  3. DevCraft banner
  4. Azib
    Azib avatar
    7 posts
    Member since:
    Jun 2012

    Posted 20 Jun 2012 Link to this post

    Thanks Nicolov

    i seem to figure out the way out of my problem with your help. But e.g. in my View i have a RadGridView ItemSource Property  bound to QueryableDomainServicesCollection in ViewModel i.e. 'qsdcvCustomers' and a RadDataForm in View bound to 'qsdcvOrders' in ViewModel. Both QSDCV use the SAME DomainContext for query and loading. e.g. var ctx = new MyWebService.MyDomainContext();

    When i SubmitChanges to any of the above two QSDCV, i believe the whole DomainContext will commit changes to the server for both entities 'Customers' and 'Orders' doesnt matter if they have been loaded via two different QSDCV?

    or do i need to use ctx.SaveChanges(); directly to the DomainContext in order to save Added Records / Edits to the Server?

    sorry if i sound very silly but i am just so confused the way it is going....

    Thanks
  5. Answer
    Nedyalko Nikolov
    Admin
    Nedyalko Nikolov avatar
    871 posts

    Posted 20 Jun 2012 Link to this post

    Hello,

    Indeed calling SubmitChanges() will affect the entire DomainContext, this is the way DomainContext work. SubmitChanges() method just call DomainContext.SubmitChanges() (just a wrapper in order to be able to use this method directly from QDSCV and RadDomainDataSource control), so the best option is to use separate "DomainContext" instances for every QDSCV (RadDomainDataSource).

    Greetings,
    Nedyalko Nikolov
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

Back to Top