Obligatory Beginner Questions

Sep 3, 2011 at 5:37 AM

Firstly, I'm excited for the potential that ShowUI has. I think it's exactly what I have been looking for, assuming I can wrap my feeble brain around it.

My goal is to take a GUI I once wrote using AutoIt and dsadd commands and update it to work with Powershell and Server 2008, all fancy and new. But I'm falling considerable short. I've read through all that I can find, including some tuts on Huddled Masses and whatnot, but I'm just not finding much; at best I've been able to find the full command list on the show-ui.com website and a few documented commands. Am I missing something obvious?

So far, I have this:

import-module ShowUI

StackPanel -ControlName 'Create User' {
    StackPanel -Margin 5 -Orientation Horizontal {
        RadioButton "_Faculty    " -Name UserType
        RadioButton "_Staff    " -Name UserType
        RadioButton "St_udent    " -Name UserType
        RadioButton "_Other    " -Name UserType
    }
    UniformGrid -Margin 5 -Columns 2 -Rows 5 {
        "First Name"
        TextBox -Name GivenName -Margin 2
        "Last Name"
        TextBox -Name Surname -Margin 2
        "User Name"
        TextBox -Name sAMAccountName -Margin 2
        "D.O.B."
        TextBox -Name DOB -Margin 2
        "Employee ID"
        TextBox -Name EmployeeID -Margin 2
    }
    CheckBox -Margin 5 #If checked, enable the TextBox below -Margin 5
    TextBox -Name Description -Text "Enter an optional description here" -Margin 5
    Button "Add To List" -Margin 2
    #Select-ViaUI -Name "Users To Create" -Height 500
    "|"
    "|"
    "There should be a list that updates right here, using Select-ViaUI?"
    "|"
    "|"
    Grid -Margin 5 -columns 2{
    Button "Edit Selected" -Margin 2 -column 0
    Button "Create Users" -Margin 2 -column 1 -HorizontalAlignment Right
    }
} -On_Loaded {$GivenName.Focus()} -Show

 

Nothing too fancy, just the layout. The goal here is to enter the information provided, hit the 'add' button. When add is clicked, it runs some logic, creates a PS Object and appends to the list. Repeat until you've added as many users as you plan on creating. That should populate a list in the indicated space. You should be able to click those entries and edit if necessary.

My main problems right now:

1) I can't figure out how to get the data out. I tried the -On_Click { Get-ParentControl | Set-UIValue -PassThru } method i saw in a few places to no avail. I honestly don't even fully get what Set-UIValue does, or why we're not using Get-UIValue, or why I can't set things to a variable without them disappearing.  

2) Can I update the information in the same window for the list portion? As mentioned, I'd want to create a new PS Object for each one, then display that information in something like a Select-ViaUI type display (thems be fancy). But, from there could I do an in-place edit? Or perhaps some other kind of edit, like re-filling out the fields with that information? Or would i have to do a separate window with a WPF Job?

3) How to take everything in that list and run it through other logic to create the users when I'm ready?

I think if I can figure that out, the rest is small change (how to disable a field, via check box, or how to make something mandatory, things like that). Once complete, I'd be more than happy to offer this and any other scripts I come up with for tutorials.

Cheers!

Coordinator
Sep 5, 2011 at 6:42 AM

OK, so ....

For the "Select-ViaUI" I'm going to recommend you NOT use that, but instead create a ListView using code like this:

New-Window -Title "Create User" {
StackPanel -ControlName 'Create User' {
    StackPanel -Margin 5 -Orientation Horizontal {
        RadioButton "_Faculty" -Name UserType
        RadioButton "_Staff" -Name UserType
        RadioButton "St_udent" -Name UserType -IsChecked:$true
        RadioButton "_Other" -Name UserType
    }
    UniformGrid -Name UserInfo -Margin 5 -Columns 2 -Rows 5 {
        "First Name"
        TextBox -Name GivenName -Margin 2
        "Last Name"
        TextBox -Name Surname -Margin 2
        "User Name"
        TextBox -Name sAMAccountName -Margin 2
        "D.O.B."
        TextBox -Name DOB -Margin 2
        "Employee ID"
        TextBox -Name EmployeeID -Margin 2
    }
        
    New-ListView -Name People -ItemsSource {
        ## This one way to create initial data, but you'd want to query SQL, a CSV or ... whatever
        ## Please excuse the ridiculous PowerShell syntax for constructing generic collections:
        New-Object System.Collections.ObjectModel.ObservableCollection[PSObject](,([PSObject[]](&{
            ## These are the actual data:
            New-Object PSObject -Property @{ UserType = "Staff"; FirstName = "Joel"; Surname  = "Bennett";  sAMAccountName  = "Jaykul"; DOB = [DateTime]'1/2/34'; EmployeeID= 123456 }
            New-Object PSObject -Property @{ UserType = "Staff"; FirstName = "Laerte"; Surname  = "Junior";  sAMAccountName  = "LaerteSqlDBA"; DOB = [DateTime]'1/23/45'; EmployeeID= 123457 }
            New-Object PSObject -Property @{ UserType = "Staff"; FirstName = "Doug"; Surname  = "Finke";  sAMAccountName  = "dfinke"; DOB = [DateTime]'12/3/45'; EmployeeID= 123458 }
        })))
    } -View {
        # WPF ListViews have a "View" -- this one has a GridView:
        New-GridView -Columns {
            # With Five columns that are data bound:
            New-GridViewColumn -Header "First Name" -DisplayMember { Binding FirstName }
            New-GridViewColumn -Header "Last Name" -DisplayMember { Binding Surname }
            New-GridViewColumn -Header "User Name" -DisplayMember { Binding sAMAccountName }
            New-GridViewColumn -Header "Birth Date" -DisplayMember { Binding DOB }
            New-GridViewColumn -Header "Employee ID" -DisplayMember { Binding EmployeeID }
        }
    } -On_Load {
        # Add-EventHandler -Input $People -SourceType GridViewColumnHeader -EventName Click { 
        ## ShowUI apologizes for the mess: this is not necessary in our next release ##
        [System.Windows.RoutedEventHandler]$EventHandler = {                         ##
            Initialize-EventHandler                                                  ##
            $ErrorActionPreference = 'stop'                                          ##
        ## ShowUI apologizes for the mess: this is not necessary in our next release ##
    
        ## We'd like to be able to sort by clicking the ColumnHeaders: 
        if($_.OriginalSource -and $_.OriginalSource.Role -ne "Padding") {
            ## We need to sort by a PROPERTY of the objects in the gridview
            ## in our example, we can just use the path that we used for binding ...
            $Sort = $_.OriginalSource.Column.DisplayMemberBinding.Path.Path
            $direction = if($Sort -eq $lastSort) { "Descending" } else { "Ascending" }
            $lastSort = $Sort
            $view = [System.Windows.Data.CollectionViewSource]::GetDefaultView( $People.ItemsSource )
            $view.SortDescriptions.Clear()
            try {
                $view.SortDescriptions.Add(( New-Object System.ComponentModel.SortDescription $Sort, $direction ))
            } catch { Write-Warning "Failed to sort.`n`n$($_|Out-String)" }
            $view.Refresh()
        }
       
        ## ShowUI apologizes for the mess: this is not necessary in our next release ##
            trap {                                                                   ##
                . Write-WPFError $_                                                  ##
                continue                                                             ##
            }                                                                        ##
        }                                                                            ##
        ## Hook the RoutedEvent from the grid headers by handling it on the ListView ##
        $People.AddHandler(                                                          ##
            [Windows.Controls.GridViewColumnHeader]::ClickEvent, $EventHandler)      ##
        ## ShowUI apologizes for the mess: this is not necessary in our next release ##
    }
    
    CheckBox -Margin 5 #If checked, enable the TextBox below -Margin 5
    TextBox -Name Description -Text "Enter an optional description here" -Margin 5
    Button "Add To List" -Margin 2 -On_Click {
        #$People.ItemsSource.Add(
        $NewUser = Get-UIValue $UserInfo
        $NewUser.UserType = $UserType.Content.Replace("_","")
        ## Add it to the ItemsSource (the data binding for the grid)
        $People.ItemsSource.Add((
            New-Object PSObject -Property $NewUser
        ))
    }  
} } -On_Closing {
    ## Output the ItemsSource (the whole collection)
    Set-UIValue $Window $People.ItemsSource
} -Show  # | New-QADUser ... or whatever


I'm off to bed now, but as far as editing, I think the easiest thing would be to add data-binding on the edit form, and just stick the SelectedItem as the DataContext for the UniformGrid ...

Developer
Sep 5, 2011 at 2:30 PM

Thanks for the write up Joel. The First Name will not show up in the ListView when you add a new one.

I solved it by changing the TextBox -Name GivenName to TextBox -Name FirstName