locked
How to implement a batch update for selected entries in a grid with values entered in a modal window RRS feed

  • Question

  • Hi,

    I have a grid with multi-select capability displaying data from a child and several parent entities. I would like to select a set of items, click a button, show a modal window with some input fields and on "Ok" update some grid columns of the selected items with the entered values (same value for all items). The values belong to several entity sets. 

    What is the best way to do this? What types of objects should I use for the input values in the modal window?

    I see several options:

    1. Using the screen designer create local properties of the types of the affected entities to edit them in the modal window and update the grid entities from their values. This seems to be tracked by the DataWorkspace, which has good (validation of the original entities available in the modal window) and bad (keeping the screen's changed state correct is difficult) effects.
    2. Using the screen designer create local properties of the types of the values and edit those. I expect this to keep the changed state clean, but validation has to be implemented again or be left to the updated grid.

    Any suggestions?

    Regards,
    Ralph


    Ralph

    Tuesday, January 15, 2013 2:49 PM

All replies

  • I add on additional "Selection" bits in the database table and use them to drive updates.

    The Selection bit columns are required and set to a defaut value of "0" (false) in the database.

    The Screen should have the Data Source SaveChanges() method always reset the selection bits to false on every save as the values should not be written back to the database.

    It would be nice if LS supported the ability to add properties (fields) to a grid.   This approch is a workaournd.

    Here's a screen shot of one of our screens with the workflow actions being selected.  The user has the option to Select or Unselect All records.

    The user can hide/show the Search Criteria section:

    I am waiting to have LS support commercial HTML components.  It should be a plug and play selection with RAD property selections.   This LS Silverlight out-of-the-box GUI is not competitive.


    Garth Henderson - Vanguard Business Technology


    Tuesday, January 15, 2013 9:27 PM
  • As I see it, the part you're having trouble with is the "unbound" properties in the modal window, not the multiple-selection, nor the processing of the selected items.

    As all controls in LightSwitch are designed to be bound to something, you'll always have trouble if you try to create unbound (scalar) properties.

    By far, the easiest way would be to create a dummy "entity", so that LightSwitch can do all the work for you, instead of you dealing with individual screen properties, & dirtying the screen's changed status when you make changes to them.

    If you create the dummy entity, you can then add a screen property, choosing the dummy entity as the data type. This makes it easy to drag the added property to the screen control tree, & change it's type to a ModalWindow control. Instant modal window, with all of the necessary properties already added for you.

    Then in the screen's Saving method, you only need one line of code to throw away the unwanted changes. Assuming the property is called MyModalProperty:

    VB:

    Me.MyModalProperty.Details.DiscardChanges()

    C#:

    this.MyModalProperty.Details.DiscardChanges();

    Or, if I've misunderstood, your #1 might only need that same one line of code.

    Yann - LightSwitch Central - Click here for FREE Themes, Controls, Types and Commands
     
    Please click "Mark as Answer" if a reply answers your question. Please click "Vote as Helpful" , if you find a reply helpful.
     
    By doing this you'll help others to find answers faster.

    Wednesday, January 16, 2013 3:12 AM
    Moderator
  • Hi Garth,

    I am using the solution Yann suggests in his book:
    setting the grid.SelectionMode = DataGridSelectionMode.Extended in the ControlAvailable handler.

    The UI is not perfect because you can come to a state where for a selected row a black triangle is shown on the left but the row does not have a highlighted blue background. Is it selected or not?

     Screenshot 1

    Marking rows seems to work for me this way. The next step is to open the modal window after clicking the marked button:

    Now it's possible to enter values and in the OK-Button handler I update the data in the grid and the tabs in the background. This is how it should work. But I keep getting an error "The context is not currently tracking the entity" when OK is clicked. For editing in the modal window I have instantiated single entities of the types of the entities shown in the screen.

    In your approach, are your checkmarks lost when you select a different page of data?


    Ralph


    Wednesday, January 16, 2013 11:53 AM
  • Hi Yann,

    you're right, my problems are about the properties edited in the modal window. I think my current implementation is similar to your proposal.

    The screen shows data from entity sets OdbDataObjects, OdbCanObjects, BitfieldStructureInits which are all related to each other. For the modal window in the screen designer I add local properties of type of the single entities OdbDataObject, OdbCanObject, BitfieldStructureInit.

    They are instantiated in MyScreen.Create() and I do a *.Details.DiscardChanges() directly after to prevent the Changed state of the screen to be set when first displayed. When I change a value of one of the dropdown list (e.g. "b_LimitCheck") in the modal window I get the error "The context is not currently tracking the entity":

    This seems strange to me because instantiating sets the Changed state and then changing a value is not tracked?


    Ralph

    Wednesday, January 16, 2013 12:18 PM
  • The values of screen properties are not tracked, even if the data type is an entity. The screen reacts to it, because it's added to the screen, but EF is not tracking it.

    I know Justin discussed this at length in one particular thread, & I can probably find a reference to it if you need to know the details, but suffice it to say, they're just not tracked. Using my dummy entity suggestion would get around that.


    Yann - LightSwitch Central - Click here for FREE Themes, Controls, Types and Commands
     
    Please click "Mark as Answer" if a reply answers your question. Please click "Vote as Helpful" , if you find a reply helpful.
     
    By doing this you'll help others to find answers faster.

    Thursday, January 17, 2013 3:25 AM
    Moderator
  • Do you mean this thread?

    A Screen Property Changed EnityState = Unchanged when value is changed

    It is very helpful. I still have problems understanding this, though. In my implementation the local properties of entity type get their EntityState set to "Added" when I assign a "new MyEntity()", and they "dirty" the screen, although they should not be tracked. 

    partial void ManageOdbItems_Created()
    {
    ...
      MultiEditOdbDataObject = new OdbDataObject();
      MultiEditOdbDataObject.Details.DiscardChanges();
    
      MultiEditDataObjectBitfieldStructureInit = new BitfieldStructureInit(); 
      MultiEditDataObjectBitfieldStructureInit.Details.DiscardChanges();
    ...
    }

    If I don't "DiscardChanges()" the screen is already dirty when it's initially shown. If I do "DiscardChanges()", it is not. But when I later set a FK Property of the "MultiEditDataObjectBitfieldStructureInit" object in the modal window, I get the error mentioned earlier.

    Just to clarify again: I don't want anything of the "MultiEdit..." objects persisted to the DB. I only want them as an container for the entered values to be assigned to the selected rows when the modal window is closed.

    I guess I have to dig a little further. It's beginning to be frustrating since it already took me several days.


    Ralph


    Thursday, January 17, 2013 2:38 PM
  • Yes, that's the thread I was talking about.

    The screen is "dirty" because a screen property value has changed, but three's no data to be persisted to the data layer, because a screen property only exists on the screen.

    There was a change in screen behaviour, from B2 to V1 (if I remember correctly). In B2, a screen opened as non-dirty, & to me that's the logical condition for it to be in - the user has made no changes. But in V1 RTM, a new entity screen opened as "dirty" straight away. I can kind of understand "why", but I don't think it's logical from a user's perspective.

    Using the method I described for multiple-selection in the grid, nothing should get "persisted" about the selected items. That's one of the draw-backs of using the checkbox method, you have to manually handle discard the "changes" made by ticking a bound checkbox.

    Or am I misunderstanding your concern?


    Yann - LightSwitch Central - Click here for FREE Themes, Controls, Types and Commands
     
    Please click "Mark as Answer" if a reply answers your question. Please click "Vote as Helpful" , if you find a reply helpful.
     
    By doing this you'll help others to find answers faster.

    Friday, January 18, 2013 8:04 AM
    Moderator
  • I understand that in my implementation the "selected state" does not get saved to the DB. It would be a little effort to handle that correctly in a multi-user environment. It would need to be saved per session. Currently I don't need that.

    What I meant regarding persistance is that the screen properties (the "MultiEdit..." objects) used for editing should not be saved to the DB. Their values are assigned to the corresponding properties of the selected grid items, when the modal window is closed.

    partial void DialogMultiEditOk_Execute()
    {
      // loop through the selected rows  
      foreach (OdbItem item in dataObjectsGrid.SelectedItems)
      {
        // OdbDataObject properties
        if (MultiEditOdbDataObject.DefaultValue.HasValue)
        {
          item.OdbDataObject.DefaultValue = MultiEditOdbDataObject.DefaultValue;
        }
        if (MultiEditOdbDataObject.MinValue.HasValue)
        {
          item.OdbDataObject.MinValue = MultiEditOdbDataObject.MinValue;
        }
        if (MultiEditOdbDataObject.MaxValue.HasValue)
        {
          item.OdbDataObject.MaxValue = MultiEditOdbDataObject.MaxValue;
        }
    
        // OdbDataObject Bitfield properties
        if (MultiEditDataObjectBitfieldStructureInit.EnumerationMember != null)
        {
          item.OdbDataObject.BitfieldStructureInit.EnumerationMember = MultiEditDataObjectBitfieldStructureInit.EnumerationMember;
        }
        if (MultiEditDataObjectBitfieldStructureInit.EnumerationMember1 != null)
        {
          item.OdbDataObject.BitfieldStructureInit.EnumerationMember1 = MultiEditDataObjectBitfieldStructureInit.EnumerationMember1;
        }
        ....
      }
    
      MultiEditOdbDataObject.Details.DiscardChanges();
      MultiEditDataObjectBitfieldStructureInit.Details.DiscardChanges();
      this.CloseModalWindow("DialogMultiEdit");
    }
    
    partial void DialogMultiEditCancel_Execute()
    {
      MultiEditOdbDataObject.Details.DiscardChanges();
      MultiEditDataObjectBitfieldStructureInit.Details.DiscardChanges();
      this.CloseModalWindow("DialogMultiEdit");
    }
    

    Maybe this illustrates my intention. Unfortunately I keep getting the error  "The context is not currently tracking the entity".


    Ralph

    Friday, January 18, 2013 8:32 AM
  • Got it working now using individual local properties for editing.

    Thanks for your responses.


    Ralph

    Monday, January 21, 2013 7:34 AM