Refresh $WPA.label multiple times with one click?

This topic contains 22 replies, has 4 voices, and was last updated by Profile photo of Mark Mark 3 months ago.

  • Author
    Posts
  • #32190
    Profile photo of cm it
    cm it
    Participant

    Hi,
    so i've been trying to create my first GUI. For this question i've made a testcase. I hava an inputfield, if this -ieq "k" then first print "ok" then change it to "lets go". At the moment, it only shows Lets go.

    $WPFbutton.Add_Click({
        if($WPFtextBox.Text -ieq "k"){
         $WPFlabel.Content = "ok"
          Write-host "Updating Window"
          sleep 5        
         $WPFlabel.Content = "lets go"
         Write-host "Updating Window 2"
        }
    })
    

    Does anyone had an example? Or a suggestion? I"ve been googeling but can't find it.

  • #32193
    Profile photo of Steven Ayers
    Steven Ayers
    Participant

    Does this do the trick?

    $WPFbutton.Add_Click({
        if($WPFtextBox.Text -ieq "k"){
         $WPFlabel.Content = "ok"
         $WPFlabel.Refresh()
          Write-host "Updating Window"
          sleep 5        
         $WPFlabel.Content = "lets go"
         $WPFlabel.Refresh()
         Write-host "Updating Window 2"
        }
    })
    
  • #32198
    Profile photo of cm it
    cm it
    Participant

    Hi Steven,

    No sadly not. I tried that before.
    I keep getting the following error:

    Updating Window
    Method invocation failed because [System.Windows.Controls.Label] does not contain a method named 'Refresh'.
    At C:\Users\9081059\AppData\Local\Temp\dc3c8e6c-4353-4d63-8fff-2d6e22b930bc.ps1:88 char:6
    +      $WPFlabel.Refresh()
    +      ~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
        + FullyQualifiedErrorId : MethodNotFound
    
  • #32199
    Profile photo of Steven Ayers
    Steven Ayers
    Participant

    Can you send me your full code? If not, try using .Refresh() against the form itself.

  • #32202
    Profile photo of cm it
    cm it
    Participant

    Sure, no problem

    $inputXML = @"
    
        
            
                
                    
                    
                
            
    
            
                
                    
                
            
            
            
            
    
            
                
                    
                        
                        
                        
                        
                    
                
            
            
            
                
                    
                
            
            
            
            
            
        
     
    "@       
     
    $inputXML = $inputXML -replace 'mc:Ignorable="d"','' -replace "x:N",'N'  -replace '^
    

    $Form.Refresh() results in :

    Method invocation failed because [System.Windows.Window] does not contain a met
    hod named 'Refresh'.
    At line:90 char:6
    +      $Form.Refresh()
    +      ~~~~~~~~~~~~~~~
        + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
        + FullyQualifiedErrorId : MethodNotFound
    

  • #32203
    Profile photo of cm it
    cm it
    Participant

    Does seem the have problem posting the code here.
    So i pasted it in pastebin : http://pastebin.com/Npbi1U6h

  • #32204
    Profile photo of Steven Ayers
    Steven Ayers
    Participant
  • #32205
    Profile photo of cm it
    cm it
    Participant

    Care to share your code πŸ™‚ ? cause no mather where i place InvalidateVisual()
    $form.InvalidateVisual() or on the label, the results stays the same :'(

  • #32244
    Profile photo of cm it
    cm it
    Participant

    Anyone else has an idea?

  • #32245
    Profile photo of Steven Ayers
    Steven Ayers
    Participant

    Have you nanaged to get a WPF label to refresh in C#? it should be a matter of copying the method from there really. Very busy day in the office but I'm curious and will investigate later if I have time

  • #32250
    Profile photo of Curtis Smith
    Curtis Smith
    Participant

    You are likely running into a common issue with PowerShell and GUIs. Since PowerShell will by default process your code as a single thread. In a lot of situations, the thread gets to processing something else, so the GUI cannot update. Check out this thread on a similar topic with a progress bar. There is also a link there to an innovative solution so that the GUI runs in a separate processing thread.

    https://powershell.org/forums/topic/progressbar-example-starting-at-wrong-value/#post-31849

  • #32251
    Profile photo of Steven Ayers
    Steven Ayers
    Participant

    I don't think you will need to start using multiple threads, as in theory you are only running a method to refresh. If you were running this at the same time as trying to run a command which would take 5 seconds to invoke, I'd probably agree.

    Powershell can use whatever assemblies you import, and doesn't lack any of the ability of other languages to actually execute, only how many process it can run simultaneously.

    could you please upload your code to pastebin again? I have some free time this afternoon.

    Also, in my WinForms, I dot this in certain places, which did fix some issues powershell had with carrying out events:

    [System.Windows.Forms.Application]::DoEvents() 
    

    WPF may require something else. As I said, if you can upload again, I will have a look.

  • #32253
    Profile photo of Curtis Smith
    Curtis Smith
    Participant

    I will be interested to see what Steven finds, but I can say for sure that I have seen this issue particularly with the start-sleep cmdlet since start-sleep keeps the thread from processing anything while it's sleeping. I will also say that I don't usually see this issue with labels. It's usually more complex form controls that I have seen this on, like progress bars.

  • #32286
    Profile photo of cm it
    cm it
    Participant

    I have created a new GUI just for testing purposes.
    It only has one button and a label that has to change twices.
    If we get this working, i can build my full GUI again.

    My application that i needed to make is done by creating a GUI typing out every item of the layout (HTML style).
    But i hope we get this working so i can use Visual Studio to create my interfaces, it will save a lot of time.

    Anyway , the pastebin : http://pastebin.com/TjWEigZ8

    And thanks again for having a look

  • #32289
    Profile photo of Steven Ayers
    Steven Ayers
    Participant
    $WPFbutton.Add_Click({
    
    	$WPFlabel1.Content = " "    
        $WPFlabel1."Getting data from AD..."
        $WPFlabel1.InvalidateVisual()
        Write-host "Updating Window"
        sleep 3
        $WPFlabel1.Content = "Succes, show results, lets go!"
        $WPFlabel1.InvalidateVisual()
        Write-host "Updating Window 2"
        
    })
    

    That works for me πŸ™‚

  • #32290
    Profile photo of cm it
    cm it
    Participant

    Really?

    I tried that before, it didn't work :/
    I tried it again now, still doesn't work.

    Name Value
    —- —–
    PSVersion 5.0.10514.6
    WSManStackVersion 3.0
    SerializationVersion 1.1.0.1
    CLRVersion 4.0.30319.42000
    BuildVersion 10.0.10514.6
    PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
    PSRemotingProtocolVersion 2.3

  • #32293
    Profile photo of Steven Ayers
    Steven Ayers
    Participant

    It's only updating once so far, which is once the method has executed.

    There are ways you can allow the label to update mid method execution, but you'd need to try to translate from C#

    To be honest, If I were you, I'd use WinForms. it's tried and tested far more than WPF, and VERY easily used in PowerShell.

    I'd try translating yourself, I want to give it a go myself too!

  • #32295
    Profile photo of cm it
    cm it
    Participant

    Yeah i created my first GUI now with WinForms. Just is a pitty that you can't "draw" your layout like WPF. But it will have to do i suppose.

    Its not that i'm unwilling but i'm new to Powershell, if i've got to learn C# too, it might be a bit too much. I want to focus my time on Powershell πŸ™‚

  • #32300
    Profile photo of Steven Ayers
    Steven Ayers
    Participant

    I was where you were 6 months ago. Once I learnt how to use Powershell syntax inside out (by doing massive complex projects in my spare time). I started on C# and it's opened up a whole other side of Powershell, namely because you can interact with .NET better.

    Good luck πŸ™‚

    I'm actually looking at getting that method to run in powershell, so I'll let you know if I get it working.

  • #32301
    Profile photo of cm it
    cm it
    Participant

    I might not be thΓ‘t talented πŸ™‚
    What projects did you work on ?

    these are things that i worked on http://pastebin.com/cJRuXnKx

  • #32677
    Profile photo of cm it
    cm it
    Participant

    Well i've been ill for the past week πŸ™
    Any luck with this?

  • #64587
    Profile photo of Mark
    Mark
    Participant

    I took time to port the above mentioned C# solution to native Powershell. It's actually almost identical to what is proposed in Microsoft's Dispatcher.PushFrame Method example.

    Function DoEvents()
    {
    	$frame = New-Object System.Windows.Threading.DispatcherFrame
    	[System.Windows.Threading.DispatcherOperationCallback]$CallBack = { $frame.Continue = $false }
    	$CurrentDispatcher = [System.Windows.Threading.Dispatcher]::CurrentDispatcher
    	$CurrentDispatcher.BeginInvoke("Background", $CallBack, $null)
    	[System.Windows.Threading.Dispatcher]::PushFrame($frame)
    }

    The forum's engine doesn't take XAML, so here's a pastebin working example: http://pastebin.com/0zgaVqKJ

    The button initiates a count to 5. Strangely, WPF updates the windows title but fails to update any child control. If you uncomment #DoEvent call it fixes it.

    Actually, there's a quicker fix. Instead you can use a one-liner calling this windows' dispatches with an empty action:

    $Window.Dispatcher.Invoke("Background", [action]{})

    To be honest I don't fully understand the coding esoterics behind it, the C# equivalents of these techniques are discussed here and the comments are ambiguous, some claim one solution is safer the others say the opposite. Go figure. But in my tests they both work and they both quirk. Sometimes they lag and fail to flush the event buffer in time.

  • #64621
    Profile photo of Mark
    Mark
    Participant

    I took time to port the above mentioned C# solution to native Powershell. It's actually almost identical to what is proposed in Microsoft's Dispatcher.PushFrame Method example.

    Function DoEvents()
    {
    	$frame = New-Object System.Windows.Threading.DispatcherFrame
    	[System.Windows.Threading.DispatcherOperationCallback]$CallBack = { $frame.Continue = $false }
    	$CurrentDispatcher = [System.Windows.Threading.Dispatcher]::CurrentDispatcher
    	$CurrentDispatcher.BeginInvoke("Background", $CallBack, $null)
    	[System.Windows.Threading.Dispatcher]::PushFrame($frame)
    }

    The forum's engine doesn't take XAML, so here's a pastebin working example: http://pastebin.com/0zgaVqKJ

    The button initiates a count to 5. Strangely, WPF updates the windows title but fails to update any child control. If you uncomment #DoEvent call it fixes it.

    Actually, there's a quicker fix. Instead you can use this one-liner calling the windows' dispatches with an empty action:

    $Window.Dispatcher.Invoke("Background", [action]{})

    To be honest I don't fully understand the coding esoterics behind it, the C# equivalents of these techniques are discussed here and the comments are ambiguous, some claim one solution is safer the others say the opposite. Go figure. But in my tests they both work and they both quirk. Sometimes they lag and fail to flush the event buffer in time.

You must be logged in to reply to this topic.