locked
Help with WPF using Posh Powershell Pro Tools Visual Studio 2017 RRS feed

  • Question

  • Hey all

    I am semi new to working heavily with PowerShell and am working on building a WPF application using Posh Powershell Pro Tools and VS 2017. I have the GUI built and designed how I want it, I just don't know how to bind the buttons and event handlers properly. Basically, I would like for the first page to have a text box to gather input, and a button to take that input and change the name of a PC.

    Here is my XAML code:

    <Window
    
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    
      Title="Windows Setup Automation" Height="350" Width="451.471">
    
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="153*"/>
                <RowDefinition Height="166*"/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="268*"/>
            </Grid.ColumnDefinitions>
    
            <Label Content="Type in value of computer name and click &quot;Set Computer Name&quot;" HorizontalAlignment="Left" Margin="10,57,0,0" VerticalAlignment="Top" Width="348" Height="26"/>
    
            <Button x:Name="firstNext" Content="Next" HorizontalAlignment="Right" VerticalAlignment="Bottom" Width="66" Margin="0,0,14,10" Height="20" Grid.Row="1" Click="firstNext_Click"/>
            <TextBox x:Name="firstComputerNameInput" HorizontalAlignment="Left" Height="22" Margin="38,90,0,0" TextWrapping="Wrap" Text="Type computer name here" VerticalAlignment="Top" Width="120" TextChanged="TextBox_TextChanged" FontStyle="Italic" FontSize="10"/>
            <Button x:Name="firstbuttonSetComputerName" Content="Set Computer Name" HorizontalAlignment="Left" Margin="163,91,0,0" Width="122" Click="firstbuttonSetComputerName_Click" VerticalAlignment="Top"/>
            <Button x:Name="firstPrevious" Content="Previous" Margin="0,0,85,10" VerticalContentAlignment="Center" Grid.Row="1" VerticalAlignment="Bottom" HorizontalAlignment="Right" Width="75" Click="firstPrevious_Click"/>
    
        </Grid>
    
    </Window>

    Here is my PowerShell code:

    function Add-ControlVariables {
    	
    New-Variable -Name 'firstComputerNameInput' -Value $window.FindName('firstComputerNameInput') -Scope 1 -Force	
    New-Variable -Name 'firstbuttonSetComputerName' -Value $window.FindName('firstbuttonSetComputerName') -Scope 1 -Force	
    New-Variable -Name 'firstPrevious' -Value $window.FindName('firstPrevious') -Scope 1 -Force	
    New-Variable -Name 'firstNext' -Value $window.FindName('firstNext') -Scope 1 -Force
    }
    
    function Load-Xaml {
    	[xml]$xaml = Get-Content -Path $PSScriptRoot\FirstPage.xaml
    	$manager = New-Object System.Xml.XmlNamespaceManager -ArgumentList $xaml.NameTable
    	$manager.AddNamespace("x", "http://schemas.microsoft.com/winfx/2006/xaml");
    	$xaml.SelectNodes("//*[@x:Name='firstComputerNameInput']", $manager)[0].RemoveAttribute('TextChanged')
    	$xaml.SelectNodes("//*[@x:Name='firstbuttonSetComputerName']", $manager)[0].RemoveAttribute('Click')
    	$xaml.SelectNodes("//*[@x:Name='firstPrevious']", $manager)[0].RemoveAttribute('Click')
    	$xaml.SelectNodes("//*[@x:Name='firstNext']", $manager)[0].RemoveAttribute('Click')
    	$xamlReader = New-Object System.Xml.XmlNodeReader $xaml
    	[Windows.Markup.XamlReader]::Load($xamlReader)
    }
    
    function Set-EventHandlers {
    
    	$firstComputerNameInput.add_TextChanged({
    		param([System.Object]$sender,[System.Windows.Controls.TextChangedEventArgs]$e)
    		TextBox_TextChanged($sender,$e)
    	})
    	$firstbuttonSetComputerName.add_Click({
    		param([System.Object]$sender,[System.Windows.RoutedEventArgs]$e)
    		firstbuttonSetComputerName_Click($sender,$e)
    	})
    	$firstComputerNameInput.add_TextChanged({
    		param([System.Object]$sender,[System.Windows.Controls.TextChangedEventArgs]$e)
    		TextBox_TextChanged($sender,$e)
    	})
    	$firstPrevious.add_Click({
    		param([System.Object]$sender,[System.Windows.RoutedEventArgs]$e)
    		firstPrevious_Click($sender,$e)
    	})
    	$firstNext.add_Click({
    		param([System.Object]$sender,[System.Windows.RoutedEventArgs]$e)
    		firstNext_Click($sender,$e)
    	})
    
    }
    
    $window = Load-Xaml
    Add-ControlVariables
    Set-EventHandlers
    
    function TextBox_TextChanged
    {
    	param($sender, $e)
    }
    
    
    function firstbuttonSetComputerName_Click
    {
    	param($sender, $e)
    }
    
    
    function firstPrevious_Click
    {
    	param($sender, $e)
    }
    
    
    function firstNext_Click
    {
    	param($sender, $e)
    }
    
    
    $window.ShowDialog()

    Any help would be greatly appreciated! Please let me know if there is any additional information I can provide.

    Tuesday, October 2, 2018 4:22 PM

All replies

  • To add an event.

    $firstbuttonSetComputerName_Click = {
        # $this is the "sender" object
        # $_ is the "EventArgs" object
    
         # code here
    }
    $firstbuttonSetComputerName.add_Click($firstbuttonSetComputerName_Click)
    


    Do not use functions as they add issues and obfuscate what is actualky happening.

    To generate object variable just do the following and all names in the XAML will become variables of the same name.

    $xaml.SelectNodes("//*[@Name]") | 
        ForEach-Object{
            Set-Variable -Name ($_.Name) -Value $window.FindName($_.Name)
    }

    The above will also simplify your code.


    \_(ツ)_/

    Tuesday, October 2, 2018 4:49 PM
  • Jrv, thank you for your help. That makes sense! So really the only thing I would need to do is add the code underneath the param line inside the function. I guess I still don't understand where the input of the text box is stored. I would assume it's stored here:

    $firstComputerNameInput.add_TextChanged({
    		param([System.Object]$sender,[System.Windows.Controls.TextChangedEventArgs]$e)
    		TextBox_TextChanged($sender,$e)
    	})

    So when I write the script block underneath the following function, would I call upon $firstComputerNameInput to grab the input of the text box?

    function firstbuttonSetComputerName_Click { param($sender, $e)

    #EXAMPLE: Script goes here calling upon $firstComputerNameInput? }

    I apologize if these questions are basic. I am just having a really hard time wrapping my head around how this GUI designer works.


    Tuesday, October 2, 2018 8:42 PM
  • I recommend learning about forms before you press on.  The contents of a control are stored in the control.   Each type of control stores the "input" in slightly different ways.  Once you understand controls in WPF then all of this become obvious although you will need to read the docs for each type of control to learn how to work with it.

    https://docs.microsoft.com/en-us/dotnet/api/system.windows.controls.textbox?view=netframework-4.7.2

    https://docs.microsoft.com/en-us/dotnet/framework/wpf/controls/

    https://docs.microsoft.com/en-us/dotnet/framework/wpf/getting-started/


    \_(ツ)_/

    Tuesday, October 2, 2018 8:50 PM
  • I will do that. Thank you again for your help.
    Tuesday, October 2, 2018 8:53 PM