locked
Can you do a screen refresh in code on a screen that is currently open from a child record update on that screen? RRS feed

  • Question

  • Hi,

    I have a list and details screen that includes tabs for child records. The child grid has a button in each line of the child grid- in this case its a button to download a file that has been previously uploaded. ( I use an add button in the child tab to create the child record in the first place).

    When I create the new child record, it indeed appears in the grid, along with the 'button' in the new line in the grid to download what has just been uploaded.

    However, that button does not execute the code when clicked unless the list and details screen has been refreshed. If you click it before refreshing the list  and details screen, it does nothing. So if refresh the list and details page  with the standard refresh button at the bottom of the list and details page and then go into that child grid and click the 'download' button- it works and carries out what I ask it to do which is to display the downloaded file.

    Is there any way to automatically refresh the list and details page 'in code' the moment the new child record is created- so that I don't have to manually click the 'refresh' button on the page? Or is there a way of making the download button in the child grid 'active' immediately upon child record creation - so that the download button functionality is kicked off without a screen refresh?

    Hope my question isn't too convoluted ...

    Saturday, October 5, 2013 9:23 PM

Answers

  • Thanks Amr.

    Based on your C# code, the following VB code worked on the screen_closing method

            Private Sub WebApiUpload_Closing(ByRef cancel As Boolean)
                Dim requestListDetailsScreen As Microsoft.LightSwitch.Client.IActiveScreen = Application.ActiveScreens.Where(Function(a) TypeOf a.Screen Is AllServiceRequests).FirstOrDefault()
                requestListDetailsScreen.Screen.Details.Dispatcher.BeginInvoke(Sub()
                                                                                   'customerListScreen.Screen.Refresh();
                                                                                   requestListDetailsScreen.Screen.Refresh()
                                                                                   'DirectCast(requestListDetailsScreen.Screen, AllServiceRequests).ServiceRequestsByTeamAndStatusType.Refresh()
    
                                                                               End Sub)
    
            End Sub

    The DirectCast statement didn't do it, but the screen refresh line above it did. It is now refreshing via code. Thanks sooooooo much. I would not have figured that out.

    I will mark as answer.

    • Marked as answer by lvsund Tuesday, October 8, 2013 9:25 PM
    Tuesday, October 8, 2013 9:25 PM

All replies

  • Could you provide a screen shot of your schema, screen layout and the code behind the button. I tried a simple scenario similar to what you have described and it worked for me. Also, provide more details on how you are doing the scenario, are you creating a new record and then try to execute the button before save or after you save?

    Monday, October 7, 2013 5:37 PM
  • Here is portion of schema:

    Its based on Paul Van Bladel's example of file upload and download shown as example in this forum. Here is screen layout portion where the file attachments are the children:

    You will notice the download button.

    Since I can have only 2 pics per message. I will save this and add another with continuation of comments

    Monday, October 7, 2013 7:57 PM
  • Here is screen shot of functionality:

    Notice the download button for each child record and new attachment link  for uploading new attachment. The latest download button only works after the screen is refreshed AFTER  the latest upload has been added.

    The add new attachment calls a new screen where I have it prompt user for a new file to upload which opens a file dialog box etc to select the file to be uploaded. When the upload is done it closes that upload page ( via code) and the person is simply left on the page they started from - not by code ( ie navigation not hardcoded back). I do a collection refresh on the screen_activate method for the main list details page- and the new attachment record shows up in the list. BUT the download button doesn't do anything until the listg details screen is refreshed. Then it  does what it is supposed to do.

    Here is code for upload button:

          Private Sub AddNewAttachment_Execute()
                Dim dataService = Me.Application.CreateDataWorkspace().ApplicationData
                Dim FileSystemUploadavailable As Boolean = dataService.ApplicConfs.FirstOrDefault.FileSystemUpload
                If FileSystemUploadavailable Then
                    Me.Application.ShowWebApiUpload(Me.ServiceRequestsByTeamAndStatusType.SelectedItem.Id)
                Else
                    Me.Application.ShowUploadViaTable(Me.ServiceRequestsByTeamAndStatusType.SelectedItem.Id)
                End If
            End Sub

    Here is code for download button:

     Private Sub Download_Execute()
    
                Dim fileStoreId As Integer = Me.FileMetaDatas.SelectedItem.Id
                'for retrieving the file, we use the FileController's Download method with as query parameter the id of the FileStore record
                Dispatchers.Main.Invoke(Sub()
                                            Dim baseAddress As New Uri(New Uri(System.Windows.Application.Current.Host.Source.AbsoluteUri), "../../")
                                            'works both in debug and deployed !
                                            Dim url As String = String.Format("{0}api/File/Download?Id={1}", baseAddress.AbsoluteUri, fileStoreId)
                                            HtmlPage.Window.Navigate(New Uri(url), "_blank")
    
                                        End Sub)
            End Sub

    Again the code is based on Paul Van Bladels upload download example ( converted from c# to vb) and it works. The only thing I am trying to figure out is how to have the download button above immediately work upon save of the  attachment child record in code or how to refresh the list details screen in code which in turn causes the download button to actually be executable. With no refresh- the button can be clicked and clicked and nothing happens.

    If you need further information please let me know. I don't know if you have all you need yet.

    Thanks

    Monday, October 7, 2013 8:16 PM
  • Hi,

    sorry I forgot to ask you this question before, did you try to debug through the code for the download button? when you say it doesn't do anything, do you mean the code is not getting executed or the code is getting executed by it is not doing anything? in my opinion, Refreshing the screen through the code is not the right approach.

    Let me know if you can debug the code in the Download_Execute() method. 

    Tuesday, October 8, 2013 2:06 PM
  • Hi Amr,

    So in debugging, it doesn't get to the download_execute code unless a screen refresh is done.

    An attachment is added via the upload button. Then that upload page is closed by code- causing you to be back in the list and details page- not by code- but rather because the list and details page hadn't been closed.

    In turning debugging on for download_execute, when you click  the download button, its like it doesn't recognize the button is there and should be doing something when clicked. Its like that area of screen doesn't believe the button is there- so clicking that area of screen on the link is like clicking thin air. so it never gets to the download_execute code .

    When I do a manual refresh of the list and details page by clicking the standard refresh button at the bottom of the page- THEN- it recognizes the link as a link and goes off and executes the download code.

    Below is the vb equivalent of Paul Van Bladel upload download example of upload page that is kicked off before the user is dropped back to the orginal list and details page:

    Imports System
    Imports System.Linq
    Imports System.IO
    Imports System.IO.IsolatedStorage
    Imports System.Collections.Generic
    Imports Microsoft.LightSwitch
    Imports Microsoft.LightSwitch.Framework.Client
    Imports Microsoft.LightSwitch.Presentation
    Imports Microsoft.LightSwitch.Presentation.Extensions
    Imports System.Windows.Browser
    Imports Microsoft.LightSwitch.Threading
    Imports LightSwitchApplication.Poco
    Imports System.Windows.Media
    Imports System.Windows.Controls
    Imports System.Windows.Media.Animation
    Imports System.Windows
    Imports System.Windows.Data
    Imports Microsoft.VisualStudio.ExtensibilityHosting
    Imports Microsoft.LightSwitch.Sdk.Proxy
    Imports System.Windows.Markup
    Namespace LightSwitchApplication
        Public Class WebApiUpload
    
            'ingredients:
            'The viewmodel needs a string property "SelectedFileName" which is NOT a parameter and is NOT required
            'the property is bound to  a Label control on the screen.
            'next to the label a custom control ( a simple system.windows.controls.button) is placed.
            'The viewmdodel needs a boolean property "IsBusy" which is NOT a parameter and is NOT required
            'the property is bound to  a custom control on the screen (the busy indicator)
            'add next to the button the busyindicator control (necessary files are in referenced assemblies folder.
            'system.windows.controls.toolkit.dll -->system.windows.controls.busyindicator
            Private Sub WebApiUpload_Created()
                IsBusy = False
    
                SelectedFileName = "Please select a file"
                Dim fileDialogCustomControl = Me.FindControl("ReadLocalFileContentButton")
                AddHandler fileDialogCustomControl.ControlAvailable, Sub(s, e)
                                                                         Dim button As Button = TryCast(e.Control, Button)
                                                                         button.Content = "..."
                                                                         RemoveHandler button.Click, AddressOf FileDialogButton_Click
                                                                         AddHandler button.Click, AddressOf FileDialogButton_Click
                                                                     End Sub
    
                Dim busyProxy = Me.FindControl("FileBusyIndicator")
                'the sole fact that the busyindicator is bound to the IsBusy viewmodel property is not enough (this is just setting up the datacontext of the custom control
                'we must still arrange that  the "IsBusyProperty" dependency property of the business indicator is "linked" to the value property of the custom control.
                AddHandler busyProxy.ControlAvailable, (Sub(s, e)
                                                            Dim busyIndicator = TryCast(e.Control, BusyIndicator)
                                                            Dim b = New Binding("Value")
                                                            b.Mode = BindingMode.TwoWay
                                                            busyIndicator.SetBinding(busyIndicator.IsBusyProperty, b)
                                                        End Sub)
            End Sub
    
    
            Private Sub FileDialogButton_Click(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs)
                Dim button As Button = TryCast(sender, Button)
                Dim openFileDialog As New OpenFileDialog()
    
                Dim fileName As String = String.Empty
                Dim binaryData() As Byte = Nothing
    
                If openFileDialog.ShowDialog() = False Then
                    SelectedFileName = String.Empty
    
    
                Else
                    SelectedFileName = "Handling the file upload. Please wait...."
                    IsBusy = True
                    Try
                        Using fileStream As FileStream = openFileDialog.File.OpenRead()
                            fileName = openFileDialog.File.Name
                            Using streamReader As New BinaryReader(fileStream)
                                binaryData = streamReader.ReadBytes(CInt(fileStream.Length))
                            End Using
                            fileStream.Close()
                        End Using
    
                    Catch e1 As IOException
                        Me.Details.Dispatcher.BeginInvoke(Sub()
                                                              Me.ShowMessageBox("IO error...")
                                                              SelectedFileName = "An error occured"
                                                              IsBusy = False
                                                          End Sub)
                    End Try
                End If
                'again as an example we attach the file to the first customer
                If binaryData IsNot Nothing Then
                    Me.StartWebApiCommand(Of FileUploadResponseParameters)("api/File/Upload", New FileUploadRequestParameters With {.BinaryData = binaryData, .FileName = fileName, .ReferenceId = RequestID, .ReferencedEntitySet = "ServiceRequests"}, Sub([error], responseParams)
                                                                                                                                                                                                                                                             IsBusy = False
                                                                                                                                                                                                                                                             SelectedFileName = fileName
                                                                                                                                                                                                                                                             If [error] IsNot Nothing OrElse responseParams.UploadStatus <> "ok" Then
                                                                                                                                                                                                                                                                 SelectedFileName = "Something went wrong..."
                                                                                                                                                                                                                                                             End If
                                                                                                                                                                                                                                                         End Sub)
                    Microsoft.LightSwitch.Threading.Dispatchers.Main.BeginInvoke(Sub()
    
                                                                                     Application.ActiveScreens.Where(Function(s) s.Screen.DisplayName = "Web Api Upload").FirstOrDefault.Close(True)
    
                                                                                 End Sub)
                End If
    
            End Sub
    
            Private Sub DownloadLatestFile_Execute()
                Dim dataService = Me.Application.CreateDataWorkspace().ApplicationData
                Dim fileStoreId As Integer = dataService.FileStores.OrderByDescending(Function(f) f.Id).First().Id
                'as an example we retrieve the latest upload.
                'for retrieving the file, we use the FileController's Download method with as query parameter the id of the FileStore record
                Dispatchers.Main.Invoke(Sub()
                                            Dim baseAddress As New Uri(New Uri(System.Windows.Application.Current.Host.Source.AbsoluteUri), "../../")
                                            'works both in debug and deployed !
                                            Dim url As String = String.Format("{0}api/File/Download?Id={1}", baseAddress.AbsoluteUri, fileStoreId)
                                            HtmlPage.Window.Navigate(New Uri(url), "_blank")
    
                                        End Sub)
    
            End Sub
    
    
    
     
    
            Private Sub WebApiUpload_Closing(ByRef cancel As Boolean)
            End Sub
        End Class
    
    End Namespace

    Tuesday, October 8, 2013 2:21 PM
  • Please ignore the downloadlatestfile_execute in code snippet above- I don't use that. The download execute code previously provided -launched from the list and details page is the download code
    Tuesday, October 8, 2013 2:24 PM
  • I should also mention that the only reason why the new child record appears in child record grid ahead of a screen refresh is because  I do try to do a collections refresh for the attachments on the screen activate method for listdetails page. If I am on any other record other than the most recent parent one, when I do the attachment- I am bounced back to the latest parent record. navigating to the  parent record where I did the attachment shows me the new attachment record- but the link isn't active until a screen refresh.

    If I am on the most current parent record and do the attachment- nothing shows up in the child grid initially because I haven't left the parent record. In that case a screen refresh makes the child record visible. And because I had to do a  screen'refresh' manually to make it visible - it then of course makes the link executable.

    So this seems to hover around a scenario that the attachment is not downloadable on the parent page unless the parent page is refreshed. So that's why I am wondering how to accomplish screen refresh in code in some fashion after a child record is created

    Tuesday, October 8, 2013 2:52 PM
  • could you post a screen shot of the code refresh you are referring to?
    Tuesday, October 8, 2013 3:02 PM
  • in the parent screen activated code

     Private Sub AllServiceRequests_Activated()
                ' Write your code here.
                Me.ServiceRequestNotes.Refresh()
                Me.IndividualAssignmentHistories.Refresh()
                Me.TeamAssignmentHistories.Refresh()
                Me.StatusHistories.Refresh()
                Me.FileMetaDatas.Refresh()
                Me.ServiceRequestsByTeamAndStatusType.Refresh()
    
            End Sub

    FileMetaData is attachments child records
    Tuesday, October 8, 2013 3:05 PM
  • Hi,

    first of all, I don't recommend your approach, it is not a good practice to refresh the data sources in the activated method, because you don't want the data to get refreshed every time you active the screen.

    The solution to your problem is to refresh the Customers (or the parent table) from the upload screen by using a code similar to this (the code I have is in C#):

     Microsoft.LightSwitch.Client.IActiveScreen customerListScreen = Application.ActiveScreens.Where(a => a.Screen is CustomersListDetail).FirstOrDefault();
                                           customerListScreen.Screen.Details.Dispatcher.BeginInvoke(() =>
                                           {
                                               ((CustomersListDetail)customerListScreen.Screen).Customers.Refresh();
                                               //customerListScreen.Screen.Refresh();
                                           });
    You can either put this code at the closing method of the screen, or put it after your upload operation finished (

    FileDialogButton_Click method). I would recommend to put it in the closing method if you are only going to upload 1 file.


    Tuesday, October 8, 2013 6:57 PM
  • Thanks Amr.

    Based on your C# code, the following VB code worked on the screen_closing method

            Private Sub WebApiUpload_Closing(ByRef cancel As Boolean)
                Dim requestListDetailsScreen As Microsoft.LightSwitch.Client.IActiveScreen = Application.ActiveScreens.Where(Function(a) TypeOf a.Screen Is AllServiceRequests).FirstOrDefault()
                requestListDetailsScreen.Screen.Details.Dispatcher.BeginInvoke(Sub()
                                                                                   'customerListScreen.Screen.Refresh();
                                                                                   requestListDetailsScreen.Screen.Refresh()
                                                                                   'DirectCast(requestListDetailsScreen.Screen, AllServiceRequests).ServiceRequestsByTeamAndStatusType.Refresh()
    
                                                                               End Sub)
    
            End Sub

    The DirectCast statement didn't do it, but the screen refresh line above it did. It is now refreshing via code. Thanks sooooooo much. I would not have figured that out.

    I will mark as answer.

    • Marked as answer by lvsund Tuesday, October 8, 2013 9:25 PM
    Tuesday, October 8, 2013 9:25 PM
  • I will also adjust code so screen activate stuff doesn't kick off- per your suggestion
    Tuesday, October 8, 2013 9:26 PM