A PowerShell WPF DSL (Part 2) – Getting Control Values

Some Background

Before I start, I should probably take a minute to explain what a DSL is and why you would want to use one.

A DSL (domain-specific language) is a (usually small) language where the vocabulary comes from a specific problem domain (or subject).  Note that this has nothing to do with Active Directory domains, so that might have been confusing.

By using words that are naturally used in describing problems in this subject, it is possible to write using the DSL in ways that look less like programming and more like describing the solution.

For instance, in Pester, you might write part of a unit test like this (3.0 syntax):

It "Has a non-negative result" {
   $result | Should Be GreaterThan 0
}

There are some aspects of this that look like PowerShell (the $, the | and the {}), but in general it doesn’t look much like code. It looks more like a description of the test that we’re writing.

In the WPF DSL that I’m describing in these posts, I want to be able to write PowerShell scripts that create WPF applications in a way that the “WPF” part of the script is easy. At least, a lot easier than trying to generate XAML or automate the WPF classes using brute force. That being said, the code in my DSL is not some sort of magic, it’s just PowerShell code.

One interesting aspect of DSLs is that because they don’t look quite like code, they often ignore coding conventions. Note that the Pester example had a PowerShell cmdlet called “It”. No verb-noun convention followed there. Also, Using positional parameters is more common in a DSL. Not a problem, just something to be aware of.

Getting Control Values

One of the problems I listed at the end of the previous post (#3) was that reading the text property won’t work once we have other controls to think about besides textboxes.

My solution here has worked out really well. I decided to add a method to any control that I would want to get a value from. The method is called GetControlValue. It is responsible for knowing how to get the values from the control (which, as part of the control object it will have no problem with).

Here’s the updated Textbox function:

function TextBox {
    [CmdletBinding()]
    Param($Name)
    $Properties = @{ Name = $name ;MinWidth=100}
    New-Object System.Windows.Controls.TextBox -Property $properties | 
        Add-Member -Name GetControlValue -MemberType ScriptMethod -Value {$this.Text} -PassThru
}

Since it’s a ScriptMethod, we get to use $this to refer to the control, so $this.Text is the value we want.

With that in place, we need to update the If statement at the end of the Window function to use the ScriptMethod. Here’s what it looks like:

if($window.ShowDialog() -or $true){
if($window.ShowDialog() -or $true){
  $output=[Ordered]@{}
  foreach($item in $controls){
    $output[$item.Name]=$item.GetControlValue()
  }
  [PSCustomObject]$output
}

Conclusion

Here’s the checklist now:

  1. Only textboxes? Need several other controls
  2. OK/Cancel
  3. With other controls, reading the text property won’t be a strategy
  4. Nested controls
  5. Populating controls
  6. Events
  7. ContextMenus
  8. Setting control properties

Stay tuned for more…

–Mike