This is a migrated thread and some comments may be shown as answers.

CRUD Operation using QSDCV and MVVM-Light

3 Answers 134 Views
DomainDataSource
This is a migrated thread and some comments may be shown as answers.
Azib
Top achievements
Rank 1
Azib asked on 15 Jun 2012, 07:16 AM
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


3 Answers, 1 is accepted

Sort by
0
Nedyalko Nikolov
Telerik team
answered on 19 Jun 2012, 10:44 AM
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 >>

0
Azib
Top achievements
Rank 1
answered on 20 Jun 2012, 08:32 AM
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
0
Accepted
Nedyalko Nikolov
Telerik team
answered on 20 Jun 2012, 08:41 AM
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 >>

Tags
DomainDataSource
Asked by
Azib
Top achievements
Rank 1
Answers by
Nedyalko Nikolov
Telerik team
Azib
Top achievements
Rank 1
Share this question
or