none
Code Not Displaying Sumary Property RRS feed

  • Question

  • I'm posting this here because I think fundamentally the problem(s) lay in my code not in screen design or data design. I'm following a tutorial I have in past from Andy Kung to create a list box mover screen for a many to many relationship combining table. The original article is gone but the archive of it can be found at archive.org in the wayback machine The Dec 11 2011 entry here https://web.archive.org/web/20111211024506/http://blogs.msdn.com/b/lightswitch/archive/2010/12/16/how-to-create-a-many-to-many-relationship-andy-kung.aspx .

    Fist of all there are two parts that require a little code the first part is defining a summary property as recommended by the article which is covered in a separate article by Beth Massi Getting the Most out of LightSwitch Summary Properties. Both Articles at written in VB as the platform Lightswitch was designed for both VB and C# articles so I have to convert the code to C# see below.

    The Andy Kung article simple defines the summary property code on the application side the way Lightswitch does with a calculated field the runs on that side. The calculated field code they use looked like this and I've done my best to define the code in C# as follows below two versions because the second version was to try and handle nulls when adding or removing entries.

    Private Sub Summary_Compute(ByRef result As String)
        result = Genre.Name
    End Sub
    partial void PanelParts_Compute(ref string result)
            {
                    result = LabPart.LabPartFullName;
            }
    partial void PanelParts_Compute(ref string result)
            {
                if (LabPart == null)
                {
                    result = LabPart.LabPartFullName ?? "None Listed";
                }
                if (LabPart.LabPartFullName  != null)
                    result = LabPart.LabPartFullName;
            }
    The problem here is that on the screen while it appears the rest of the instructions to setup two columns below the details of a selected entry in the parent entity to show a list control of both the associated children properties set to the parent entity, and a second list of all of the possible Lab Parts currently available. The Available Lab Parts show up in the list but when I use the buttons coded to add Lab Parts to a panel they do not show up in the other list and blindly hitting delete on the empty rows throws the null exception to indicate there is nothing to remove. In this case I'm assembling Lab Panels from their Lab Parts the screen looks like the following with a third column in the middle for the add remove buttons. I will show the original VB code and the C# sharp code I'm have as well to define the buttons methods of action.

    Nothing shows up in here when a Lab Panel is selected or a Lab Part is added to that Lab Panel with the buttons defined in code. Not even a sort header shows up for this list control like it does for the available Lab Parts list next to this one.

    This is the VB code example for the many to many screen buttons for movie genres and the code I've modified to work for a C# screen for assembling Lab Panels with Lab Parts.

            Private Sub AddGenre_Execute()
                If (Genres.SelectedItem IsNot Nothing) Then
                    Dim mg As MovieGenre = MovieGenres.AddNew()
                    mg.Movie = Me.MovieProperty
                    mg.Genre = Genres.SelectedItem
                End If
            End Sub
     
            Private Sub RemoveGenre_Execute()
                MovieGenres.DeleteSelected()
            End Sub

     partial void AddLabPart_Execute()
            {
            if (LabPanelAssembledParts.SelectedItem != null)
                {
                    bool LabPartExists = false;
                    foreach (LabPanelAssembledPart mgSearch in this.LabPanelAssembledParts)
                        {
                            if (mgSearch.LabPart.LabPartFullName == this.LabPart.SelectedItem.LabPartFullName)
                            {
                                LabPartExists = true;
                            }
                    }
    
                    if (LabPartExists == true)
                    {
                        ScreenExtensions.ShowMessageBox(this, "'Lab Panel Part' already exists");
                    }
                    else
                    {
                        LabPanelAssembledPart lpap = LabPanelAssembledParts.AddNew();
                        lpap.LabPanel = this.LabPanelProperty;
                        lpap.LabPart = LabPart.SelectedItem;
                    }
                }
            }
    
            partial void RemoveLabPart_Execute()
            {
                LabPanelAssembledParts.DeleteSelected();
            }

    I'm pretty sure the problem again is somehow related to the code not building the screens as all of the instructions for this example are straight forward otherwise.


    • Edited by reigh7 Thursday, December 27, 2018 6:16 PM fixing broken link
    Thursday, December 27, 2018 6:14 PM

All replies

  • To be clear Lightswitch is no longer supported. If you're moving away from LS then you're good. If you're trying to get LS to work then you need to convert to something else instead.

    The first version of your Compute method would work if LabPart is not null and is equivalent to the VB code. The second version isn't handling nulls properly and will crash if LabPart is null. The first if statement is checking to see if LabPart is null and if it IS then dereferencing it and causing a crash. The second if statement is fine but if you're using a newer version of C# then you can simplify the code dramatically.

    private void PanelParts_Compute ( ref string result )
    {
       result = LabPart?.LabPartFullName ?? "None Listed";
    }

    Note that you shouldn't be using partial at all. Also you should really return the string, not set a ref parameter. Ref parameters are almost always the wrong solution. 

    In your second set of code I'm having a hard time understanding why you're doing what you're doing. The first if statement looks to see if there is a selected item. If there is then you have the (I assume LabPart). You then use a foreach to search all the parts comparing them to some new object called LabPart.SelectedItem. Are you really sure this is the correct logic? What does the SelectedItem in the if statement have to do with the foreach loop at all? The rest of the logic looks similar to what you had in VB but note, again, LS is no longer supported. You need to move away from it as it won't work on newer systems in the future.

    Finally note that in VB (and probably LS) there was the convention that a method that matched the control/event name would automatically be hooked up to the event (or at least the designer generated it this way). So behind the scenes the control(s) had events that were set to the method that was created. If you're writing this code manually then you'll have to hook up the events yourself otherwise they won't be called. Since LS isn't supported anymore I have no way of verifying how it worked.


    Michael Taylor http://www.michaeltaylorp3.net

    Thursday, December 27, 2018 7:06 PM
    Moderator
  • this is only being used to prototype basics and will in no way ever be implemented the code. In the second half you are reading is from a known working example and I'm working with that legacy version it worked in. The function of the code is the same. It adds a associated entry on a combining table for creating a many to many between a whole Lab Panel Add to specifically selected above and the lab parts selected and added to the Panel. At this point I would just like to finish the prototype to show my grandma before she dies it will not be a product for sale. I am not an architect or a computer scientist in a professional sense I had to give up on that delusion of making this a product a while ago.


    To be clear in the first example I am showing an evolution of code. First of all even the people writing this article from the Lightswitch team used ref parameters. I copied their model and am simple including the code from the first article plus my attempts to handle nulls in C# vs VB. The firs article referenced the second article about the Summary property and how to customize it which primarily covered how to concatenate and make a combined field strings for displaying full name vs just a first name. Secondly it is included because the table in this case the combining table for a in the middle of a many to many relationship needed a summary property to display for this tutorial in with a list control. It is the list control displaying for each the summary properties in this case the for each panel list of Lab part names now associated on the data grid for that combining table shown as a list instead of a grid view as defined by the tutorial again. However just to let you know showing a grid  also does not show any Lab Parts when I used the button code in the second half that I converted from their VB and the updated suggested VB in the comments of the article to add entries of lab parts associated with lab panels. I do know this has definably worked and the functionality has not been removed from legacy versions of Lightswitch I'm just unsure if my code is right given I'm the one translating between VB and C#. My model has always used C# which is one of four models supported VB or C# on desktop or VB or C# for HTML this is C# for desktop their example was VB on desktop. There is way less writing my own code and built in control and properties that don't have to be manually written in JavaScript in the non HTML flavors. I feel that desktop is more robust and has access to the local file system method to run application and open files on the desktop as well as the wider range of control I mentioned for tis prototype to function even if it's just due to my skill set.
    • Edited by reigh7 Friday, December 28, 2018 3:12 PM added info
    Friday, December 28, 2018 2:51 AM
  • Make the changes to the code that I mentioned. Then verify the events are properly wired up (by verifying they are being called). If all that works you should be able to step into your code to verify the behavior. If it isn't then post an update on what isn't working still. LS was very much a "simple designer" so it did a lot of things automatically. Without being able to see all that it is hard to point you in the right direction at this time. With your update we'll move on to the next issue. If your code is hosted in GitHub or something then you could also send a link to it and we can just download your code.

    Michael Taylor http://www.michaeltaylorp3.net

    Friday, December 28, 2018 2:57 PM
    Moderator
  • I changed the code everything after the first ? is underlined red. it says syntax error : is expected.

    Events are not exposed like in windows forms in LightSwitch they never were. Those that are listed specifically are very limited. These buttons are built in controls you can simply add on to a screen and define the method they use. The above example in VB is all that was ever needed to add a button you don't have a way or need to define it at onclick or whatever else. Also to note the list control on the right is working fine I besides handling nulls right for the summary property I think there is fundamentally something wrong with the code the buttons use to add rows to combining table for this many to many. I know this before years ago with ease and the list control should immediately show what is added and it's not showing anything even after using save or refresh. It would  be easier to diagnosis the null values in the summary property is I knew if the delete button was actually deleting something or not. Non of these controls are effected by windows update this is an offline machine.

    Sunday, December 30, 2018 12:12 AM
  • "I changed the code everything after the first ? is underlined red. it says syntax error : is expected. "

    You must not be using the later versions of C# then where null conditional was introduced. Here's the equivalent code.

    private void PanelParts_Compute ( ref string result )
    {
       var fullName = (LabPart != null) ? LabPart.LabPartFullName : null;
    
       result = (fullName != null) ? fullName : "None Listed";
    }
    As for the rest of your code I recommend putting breakpoints in the update and delete logic. Then step through the code. If the breakpoints aren't being hit then the code is not properly hooked up. If it is being hit then you can step through to diagnose why it isn't behaving correctly. Since we don't have LS we cannot really try it ourselves. The code you posted for adding lab parts seems logically correct. Of course it is doing a lot more than what the VB code did but it seems correct to me.


    Michael Taylor http://www.michaeltaylorp3.net

    Sunday, December 30, 2018 4:06 AM
    Moderator
  • Uh not sure all I had to do was get rid of the "?" half null coalescing operator. LabPart is a table name to walk to the field I'm setting as a summary property you use the . period operator. Table.Field I've seen the use of ?? null coalescing before quote "It returns the left-hand operand if the operand is not null; otherwise it returns the right hand operand" the following could work on it's own.

    private void PanelParts_Compute ( ref string result )
    {
       result = LabPart.LabPartFullName ?? "None Listed";
    }

    I am only getting a run time error when I try clicking the button to remove an entry from the Linking Table (also known as a combined table in Lightswitch) It's then that the code breaks. I'm first trying to make sure I am actually entering tuples(rows) into the linking table to begin with. I don't think to handle nulls for the remove buttons button code that it will help to use ?? to return a right handed string of any kind. I think the code breaks because it is trying to remove tuples/rows that are not only null but in fact there are no rows to remove there has to be an exception to somehow say that. But, first of all I have to figure out why it's not adding rows to the linking table which is why since the summary property appears to be setup properly that nothing shows up in the list of those summary properties for that linking table.

    Sunday, December 30, 2018 11:24 PM
  • "the following could work on it's own."

    That isn't equivalent to what you originally had. If LabPart is null then your code crashes. In your original code you were checking for LabPart being null, hence why I originally went with ?. (null coalescing) Without null coalesce the larger expression is needed if LabPart can be null.

    So your RemoveLabPart_Executed is failing? That just has a single method call. Wrap that call in a try-catch and you can see the actual error.

    partial void RemoveLabPart_Execute ()
    {
       try
       {
          LabPanelAssembledParts.DeleteSelected();
       } catch (Exception e)
       {
       };
    }

    As I mentioned, your add method seems logically correct. Ultimately if LabPartExists is false then it adds the item (which is the same logic as your original sample VB code). Put a breakpoint in this method and step through it to verify it is behaving correctly.

    I don't know what DeleteSelected does so you'll need to verify that whatever state it requires is set up properly for deletion to work. Handling the exception as given above may indicate what is failing (e.g. a field not being set). However I don't know that the add is related to that. If you start out with an empty set of parts then there wouldn't be an easy way to test delete without add but if you already have parts then you shouldn't need to call add before delete which eliminates add as having issues. However if you can remove existing items but not new items then it is an add issue. This is where stepping through with the debugger in addition to using the Locals window can really help identify what is going on.


    Michael Taylor http://www.michaeltaylorp3.net

    Sunday, December 30, 2018 11:41 PM
    Moderator
  • I think the disconnect is that LabPart is not a field LabPart is the Table/Entities name I'm grabbing the field from. The table either is or isn't I would get error just trying to define it if it was not an available entity. Also I thought about it and it does not need any null handling because the field I'm calling is already required and a candidate for a primary key unless I want to allow LabParts with duplicate names which at this this is unnecessary. The facilities would have a standard to evaluate lab part ranges by. The only exception could come in the form of a set of external standard practice values and internal standards for various reasons I won't go into. As with the models of medications I've explore before though I can use an RIA service to combine two tables using negative key values for External Evidenced Based Practice, and positive key values Internal House or Experimental Based Practice, and use a summary property there to tag them with the word External and Internal or something like that for the user. Either way the full name will never be null because it is required and users already cannot put entries in without it. Behind the scenes Lightswitch has always taken care of empty tables.

    I thought it might be why I was running into issues as I though as well the add button looked right. I was going to several part of the instructions that were involved but less directly. Since the instruction referenced a separate set of instruction about summary properties I though it might be an issue there. I also was getting the error about nulls while deleting entries. I'll try and step through a try catch on the delete entries button to see if it will show if there is even a value it's deleting. I still sort of think because the list is not showing any of the values I add that the delete method is deleting rows from a table with no rows. After I figure out how to make sure rows are being added and shown to the user I'll have to make sure deleting rows without being able to select a row will be handled somehow.

    Tuesday, January 1, 2019 9:12 PM
  • I have an update I decided to go back to the start now that I have more certainty on my summary field but it seems to be coming back to that either way. First though I fixed some things in code that are starting to work now so progress first.

    When I went back and built the screen again with a new name and then had to modify the button code for that screens name I noticed I had codded some things wrong. using the VB sample, what I had and the C# sample from the comments I came up with the following. Once I did this the progress is that I can now see the Lab Part items pop up on the list when I add them and a message box if they are duplicates. The issue is still surrounding nulls though and I'm not sure why since all of the Lab Parts have full names but I get a exception that nulls are unhandled and it seems to say it wants me to use the new keyword to define a new object after determining if the object is null. I am using our previous null coalescing just to be safe still but that isn't working either. below I will post my new button code and screen shots of the error.

            partial void AddLabPart_Execute()
            {
                // Write your code here.
                //LabPart is a collection shown in the list for this List control values are from the LabPart Table
                //Code refers to the item in the list selected using the list control
                if (LabPart.SelectedItem != null)
                {
                    //LabPanelAssembledPart is the tabble entity for the many to many relationship between LabPanel and Labpart tables
                    //This tests to see if the assembled Panel has been created before to hold associated Lab Parts
                    LabPanelAssembledPart lpExists = new LabPanelAssembledPart();
                    //then a loop searches the mapping/linking table for items displayed on the screen named LabPanelAssembledParts(LabPanelAssembledParts1)
                    //the loop goes through to figure out the Lab Parts Names to include in the current list control for the the assembled Panel
                    //this property LabPart.LabPanelFullName is the name given to a primary value of Lab Parts in refernt to the full name not abreviation
                    //the full name is a required field of the Lab Parts table and is also used as the summary property for the Linking many to many table
                    foreach (LabPanelAssembledPart lpSearch in this.LabPanelAssembledParts1)
                    {
                        if (lpSearch.LabPart.LabPartFullName == this.LabPart.SelectedItem.LabPartFullName)
                        {
                            lpExists = lpSearch;
                        }
                    }
                    //After the existstance of the parts is determined already and if it does not yet exist it is added to the many to many linking table
                    //The selected Lap Part on the right will be added and displayed on the list control for that entity on the Left which is set to this Panel Selected above 
                    if (lpExists == null || lpExists.LabPart == null)
                    {
                        LabPanelAssembledPart lpap = LabPanelAssembledParts1.AddNew();
                        lpap.LabPanel = this.LabPanelProperty;
                        lpap.LabPart = LabPart.SelectedItem;
                    }
                    //If the selected Lab Part already exists and the user trys to add it to the entity this message will pop up instead
                    else
                    {
                        ScreenExtensions.ShowMessageBox(this, LabPart + " already exists");
                    }
                }
            }
    
            partial void RemoveLabPart_Execute()
            {
                // Write your code here.
                LabPanelAssembledParts1.DeleteSelected();
            }
        }
    }

    Exception error

    Details of the Exception

    Wednesday, January 2, 2019 7:56 AM
  • LabPart is null. As I mentioned before your code isn't doing the same thing as the ?. code I originally posted. You are accessing LabPart's property. If LabPart is null (which it is here) then it throws an exception. Since LabPart is null you'll need to handle that.

    //Equivalent to LabPart?.LabPartFullName ?? "None List"
    result = ((LabPart != null) ? LabPart.LabPartFullName : null) ?? "None Listed";
    I don't know why LabPart would be null because none of that code is listed. I would recommend you look at every place you expect LabPart to be set and verify it is getting set.


    Michael Taylor http://www.michaeltaylorp3.net

    Wednesday, January 2, 2019 6:40 PM
    Moderator
  • Thank for all your help I can't fix it something is wrong with the databinding that's baked in for some reason it doesn't work and don't have access to fix it that I know of. I appreciate all your hard work to help me think out the issues so I'm not on my own.

    These screen controls are pushing the "name" selected from the panel names table list to the lab Panel text box but something isn't wired up right. Without adding any Lab Parts to the Panel the first data entry error when selected opens a quick dialog window making me retype the panel name for that text box. That is not normal behavior for this tutorial it should save the name selected and shared by the text box once save is selected. I think the same sort of disconnect may be present in the assembled screen. There are two errors listed for every row added by selecting and adding a Lab Part which does show up in the assembled list using the summary property for the table similarly to how the name showed up in the Lab Panel text box. This could be that the properties Lab Panel and Panel Parts fields are not connecting possible the second error is the field/property for Lab Panel name selected and added for every row.
    I eliminated all other extra code run on the application side in calculated fields to narrow this down as well (that also means I'm still running a very flat model I have some ideas about normalizing the sets of ranges possibly complexity is reduced for now some of the stuff bein handled by a single user pivot table model will have to be move to loops in the application tier to flatten out the model to handle creating the concatenated summary scrips for the flattened pivot tables of labs by panel sliced by patient, The loops will also need to handle comparison of row to row for trend of lab value changes direction high or low, the updated model will match the model and code for calculating age and physiological sex, in the patient personal information entity, consider making that entity more normalized as well to allow for creation of future determined variables for determining laboratory results and medication administration). If I correct the Panel name that eliminates the first error. In the workflow though I still get two errors for each row after that first error is taken care of as described above. If I try and add parts before I correct the Panel Name error I cannot get to the quick dialog In that case as with when it's not corrected the debugger thinks there are issues with nulls at the summary property we have set up to write "non listed". Again even that should not be needed because we have no nulls and the field is required to enter Lab Parts into that table. It has to be a similar disconnect in the way that the Panel name is not connecting so I can save it but something is different because it's not even offering a quick dialog to fix the rows. Much of these controls and code written to create them are not exposed or available to trace with breaks to see if the values are window shows more detail.

    So thank you for trying to help me out but I don't see how this resolvable on my own and I've already shown what I could on a visit to my family. Not much else to do but I am studying older texts on application development so I may be able to write Universal Windows Applications in the future by building more of the blocks on my own with these skills. Not holding out much hope of that though my mental health is already pretty weak.

    Tuesday, January 22, 2019 12:30 AM
  • The Whole Plan had looked something like this...

    Tuesday, January 29, 2019 10:26 PM