├── Assembly ├── Courtesy of MDIX project ├── MaterialDesignColors.dll └── MaterialDesignThemes.Wpf.dll ├── CommonFunctions.ps1 ├── CommonTheme.ps1 ├── Content of Examples.txt ├── Example.config ├── Example1.ps1 ├── Example1.xaml ├── Example11.ps1 ├── Example11.xaml ├── Example13.config ├── Example13.ps1 ├── Example13.xaml ├── Example15.ps1 ├── Example15.xaml ├── Example17.ps1 ├── Example17.xaml ├── Example2.ps1 ├── Example2.xaml ├── Example3.ps1 ├── Example3.xaml ├── Example4.ps1 ├── Example4.xaml ├── Example6.ps1 ├── Example6.xaml ├── Example7.ps1 ├── Example7.xaml ├── Example8.ps1 ├── Example8.xaml ├── Example9.ps1 ├── Example9.xaml ├── Example9b.ps1 ├── Example9b.xaml ├── README.md ├── Resources └── Images │ ├── mr_bean.jpg │ └── mr_bean_tiny.jpg └── cars.csv /Assembly/Courtesy of MDIX project: -------------------------------------------------------------------------------- 1 | https://github.com/MaterialDesignInXAML/MaterialDesignInXamlToolkit 2 | -------------------------------------------------------------------------------- /Assembly/MaterialDesignColors.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrHalfBaked/PowerShell.MaterialDesign/e53a8b2c2e8e28a7c5c40d15fac4cb78b562d00b/Assembly/MaterialDesignColors.dll -------------------------------------------------------------------------------- /Assembly/MaterialDesignThemes.Wpf.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrHalfBaked/PowerShell.MaterialDesign/e53a8b2c2e8e28a7c5c40d15fac4cb78b562d00b/Assembly/MaterialDesignThemes.Wpf.dll -------------------------------------------------------------------------------- /CommonFunctions.ps1: -------------------------------------------------------------------------------- 1 | ########### 2 | # Learn how to build Material Design based PowerShell apps 3 | # 4 | # Common Functions, Variables and Assemblies 5 | # 6 | # Avi Coren (c) 7 | # Blog - https://www.materialdesignps.com 8 | # Github - https://github.com/DrHalfBaked/PowerShell.MaterialDesign 9 | # LinkedIn - https://www.linkedin.com/in/avi-coren-6647b2105/ 10 | # 11 | # Last file update: Dec 23, 2021 04:30 12 | # 13 | [Void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework') 14 | [Void][System.Reflection.Assembly]::LoadFrom("$PSScriptRoot\Assembly\MaterialDesignThemes.Wpf.dll") 15 | [Void][System.Reflection.Assembly]::LoadFrom("$PSScriptRoot\Assembly\MaterialDesignColors.dll") 16 | 17 | [regex]$Script:RegEx_Numbers = '^[0-9]*$' 18 | [regex]$Script:RegEx_AlphaNumeric = '^[a-zA-Z0-9]*$' 19 | [regex]$Script:RegEx_Letters = '^[a-zA-Z]*$' 20 | [regex]$Script:RegEx_LettersSpace = '^[\sa-zA-Z]*$' 21 | [regex]$Script:RegEx_AlphaNumericSpaceUnderscore = '^[\s_a-zA-Z0-9]*$' 22 | [regex]$Script:RegEx_NoteChars = '^[\s_\"\.\-,a-zA-Z0-9]*$' 23 | [regex]$Script:RegEx_EmailChars = '^[\@\.\-a-zA-Z0-9]*$' 24 | [regex]$Script:RegEx_EmailPattern = '^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$' 25 | [regex]$Script:RegEx_NumbersDash = '^[\-0-9]*$' 26 | 27 | # New-Window - Sets a new WPF window from a xaml file and declares all named elements as variables. It will also optionally set a Snackbar Queue. 28 | # New-Snackbar - Generates a Snackbar message with an optional button. 29 | # Set-NavigationRailTab - Accepts a TabControl and tab name parameters and sets the tab name as selected tab. 30 | # Get-NavigationRailSelectedTabName - Returns the name of the current selected tab of a TabControl. 31 | # Get-SaveFilePath - Opens a save-file windows dialog and returns the name and path of the file to be saved. 32 | # Get-OpenFilePath - Opens a open-file windows dialog and returns the name and path of the file to be opened. 33 | # Open-File - Opens a file and gets its content based on the FileType parameter. default is Get-Content. 34 | # Set-CurrentCulture - Sets the PS Session's culture. All Time and Date UI controls will be effected by that. (DatePicker for example). 35 | # Set-OutlinedProperty - Alters the visual style of some properties of a Material Design outlined UI control. 36 | # Set-ValidationError - (1)Marks/Clears an element's validity, (2)Will return an element vaildity state, (3)Will set an error message for invalid element. 37 | # Confirm-RequiredField - Will call Set-ValidationError to Mark/Clear an element if its text is $null or not respectively. 38 | # Confirm-TextPatternField - Will call Set-ValidationError to Mark/Clear an element if its text does not match or matches a regular expression respectively. 39 | # Confirm-TextInput - Blocks character from entered into an input element, based on a regular expression match 40 | 41 | function New-Window { 42 | param ( 43 | $XamlFile, 44 | [Switch]$NoSnackbar 45 | ) 46 | 47 | try { 48 | [xml]$Xaml = (Get-content $XamlFile) 49 | $Reader = New-Object System.Xml.XmlNodeReader $Xaml 50 | $Window = [Windows.Markup.XamlReader]::Load($Reader) 51 | 52 | $Xaml.SelectNodes("//*[@Name]") | ForEach-Object { Set-Variable -Name ($_.Name) -Value $Window.FindName($_.Name) -Scope Script } 53 | # Objects that have to be declared before the window launches (will run in the same dispatcher thread as the window) 54 | if (!$NoSnackbar){ 55 | $Script:MessageQueue = [MaterialDesignThemes.Wpf.SnackbarMessageQueue]::new() 56 | $Script:MessageQueue.DiscardDuplicates = $true 57 | } 58 | 59 | return $Window 60 | } 61 | catch { 62 | Write-Error "Error building Xaml data or loading window data.`n$_" 63 | exit 64 | } 65 | } 66 | 67 | function New-Snackbar { 68 | param ( 69 | $Snackbar, 70 | $Text, 71 | $ButtonCaption 72 | ) 73 | try{ 74 | if ($ButtonCaption) { 75 | $MessageQueue.Enqueue($Text, $ButtonCaption, {$null}, $null, $false, $false, [TimeSpan]::FromHours( 9999 )) 76 | } 77 | else { 78 | $MessageQueue.Enqueue($Text, $null, $null, $null, $false, $false, $null) 79 | } 80 | $Snackbar.MessageQueue = $MessageQueue 81 | } 82 | catch{ 83 | Write-Error "No MessageQueue was declared in the window. Make sure -NoSnackbar switch wasn't used in New-Window`n$_" 84 | } 85 | } 86 | 87 | function Set-NavigationRailTab { 88 | param ( 89 | $NavigationRail, 90 | $TabName 91 | ) 92 | $NavigationRail.SelectedIndex = [array]::IndexOf((($NavigationRail.Items | Select-Object -ExpandProperty name).toupper()), $TabName.ToUpper()) 93 | } 94 | 95 | function Get-NavigationRailSelectedTabName { 96 | param ( 97 | $NavigationRail 98 | ) 99 | return $NavigationRail.Items | Where-Object {$_.IsSelected -eq "True"} | Select-Object -ExpandProperty name 100 | } 101 | 102 | function Get-SaveFilePath { 103 | Param ( 104 | [string] $InitialDirectory, 105 | [string] $Filter 106 | ) 107 | try { 108 | $SaveFileDialog = [Microsoft.Win32.SaveFileDialog]::New() 109 | $SaveFileDialog.initialDirectory = $InitialDirectory 110 | $SaveFileDialog.filter = $Filter 111 | $SaveFileDialog.CreatePrompt = $False; 112 | $SaveFileDialog.OverwritePrompt = $True; 113 | $SaveFileDialog.ShowDialog() | Out-Null 114 | return $SaveFileDialog.filename 115 | } 116 | catch { 117 | Write-Error "Error in Get-SaveFilePath common function`n$_" 118 | } 119 | } 120 | 121 | function Get-OpenFilePath { 122 | Param ( 123 | [string] $InitialDirectory, 124 | [string] $Filter 125 | ) 126 | try{ 127 | $OpenFileDialog = [Microsoft.Win32.OpenFileDialog]::New() 128 | $OpenFileDialog.initialDirectory = $InitialDirectory 129 | $OpenFileDialog.filter = $Filter 130 | # Examples of other common filters: "Word Documents|*.doc|Excel Worksheets|*.xls|PowerPoint Presentations|*.ppt |Office Files|*.doc;*.xls;*.ppt |All Files|*.*" 131 | $OpenFileDialog.ShowDialog() | Out-Null 132 | return $OpenFileDialog.filename 133 | } 134 | catch { 135 | Write-Error "Error in Get-OpenFilePath common function`n$_" 136 | } 137 | } 138 | 139 | function Open-File { 140 | param( 141 | $Path, 142 | $FileType 143 | ) 144 | try { 145 | if (!(Test-Path $Path)) { 146 | Write-error "File $Path not found" 147 | return 148 | } 149 | switch ($FileType) { 150 | "xml" { 151 | [xml]$OutputFile = (Get-content $Path) 152 | } 153 | "csv" { 154 | $OutputFile = (Import-Csv -Path $Path -Encoding UTF8) 155 | } 156 | default { 157 | $OutputFile = (Get-content $Path) 158 | } 159 | } 160 | return $OutputFile 161 | } catch { 162 | Write-error "Error in Open-File common function`n$_" 163 | } 164 | } 165 | 166 | function Set-CurrentCulture { 167 | param( 168 | $LCID = 2057 169 | ) 170 | # 2057 = English (UK) , 1033 = English (US) 171 | $culture = [System.Globalization.CultureInfo]::GetCultureInfo($LCID) 172 | [System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture 173 | [System.Threading.Thread]::CurrentThread.CurrentCulture = $culture 174 | } 175 | 176 | 177 | function Set-OutlinedProperty { 178 | param ( 179 | [System.Management.Automation.PSObject[]]$InputObject, 180 | $Padding, # "2" 181 | $FloatingOffset, # "-15, 0" 182 | $FloatingScale, # "1.2" 183 | $Opacity, # "0.75" 184 | $FontSize 185 | ) 186 | try { 187 | foreach($UIObject in $InputObject) { 188 | if($Padding){ 189 | $UIObject.padding = [System.Windows.Thickness]::new($Padding) 190 | } 191 | if($FloatingOffset){ 192 | [MaterialDesignThemes.Wpf.HintAssist]::SetFloatingOffset( $UIObject, $FloatingOffset) 193 | } 194 | if($FloatingScale){ 195 | [MaterialDesignThemes.Wpf.HintAssist]::SetFloatingScale( $UIObject, $FloatingScale) 196 | } 197 | if($FontSize){ 198 | $UIObject.FontSize = $FontSize 199 | } 200 | if($Opacity){ 201 | $UIObject.Opacity = $Opacity 202 | } 203 | $UIObject.VerticalContentAlignment = "Center" 204 | 205 | } 206 | } 207 | catch { 208 | Write-Error "Error in Set-OutlinedProperty common function`n$_" 209 | } 210 | } 211 | 212 | function Set-ValidationError { 213 | param ( 214 | $UIObject, 215 | $ErrorText, 216 | [switch]$CheckHasError, 217 | [switch]$ClearInvalid 218 | ) 219 | #https://coderedirect.com/questions/546371/setting-validation-error-template-from-code-in-wpf 220 | # !!! you must put Text="{Binding txt}" in the textbox xaml code. 221 | $ClassProperty = 222 | switch($UIObject.GetType().name) { 223 | "TextBox" {[System.Windows.Controls.TextBox]::TextProperty} 224 | "ComboBox" {[System.Windows.Controls.ComboBox]::SelectedItemProperty} 225 | "TimePicker" {[MaterialDesignThemes.Wpf.TimePicker]::TextProperty} 226 | "DatePicker" {[System.Windows.Controls.DatePicker]::SelectedDateProperty} 227 | # For RatingBar - you must put this in the xaml part --> Value="{Binding Path=BlaBla, Mode=TwoWay}" . Also don't use the Validation.ErrorTemplate attribute. It will show red border, no text. 228 | "RatingBar" {[MaterialDesignThemes.Wpf.RatingBar]::ValueProperty} 229 | #"Calendar" {[System.Windows.Controls.Calendar]::SelectedDateProperty} Wasn't tested yet 230 | #"ListBox" {[System.Windows.Controls.ListBox]::SelectedItemProperty} Wasn't tested yet 231 | #"RadioButton" {[System.Windows.Controls.RadioButton]::IsCheckedProperty} Wasn't tested yet 232 | # "PasswordBox" {[system.Windows.Controls.PasswordBox]::Password} Wasn't tested yet 233 | #"RichTextBox" {[System.Windows.Controls.RichTextBox]::Document} Wasn't tested yet 234 | 235 | } 236 | [System.Windows.Data.BindingExpression]$bindingExpression = [System.Windows.Data.BindingOperations]::GetBindingExpression( $UIObject, $ClassProperty) 237 | [System.Windows.Data.BindingExpressionBase]$bindingExpressionBase = [System.Windows.Data.BindingOperations]::GetBindingExpressionBase($UIObject, $ClassProperty); 238 | [System.Windows.Controls.ValidationError]$validationError = [System.Windows.Controls.ValidationError]::new([System.Windows.Controls.ExceptionValidationRule]::New(),$bindingExpression) 239 | 240 | <# This option will put the error message on either Absolute,AbsolutPoint,Bottom,Center,Custom,Left,Right,Top,MousePoint,Mouse,Relative,RelativePoint. Default is bottom. 241 | [MaterialDesignThemes.Wpf.ValidationAssist]::SetUsePopup($UIObject,$true) 242 | [MaterialDesignThemes.Wpf.ValidationAssist]::SetPopupPlacement($UIObject,[System.Windows.Controls.Primitives.PlacementMode]::Top) 243 | #> 244 | if($CheckHasError){ 245 | return [System.Windows.Controls.Validation]::GetHasError($UIObject) 246 | } 247 | else { 248 | if ($ClearInvalid){ 249 | [System.Windows.Controls.Validation]::ClearInvalid($bindingExpressionBase) 250 | } 251 | else{ 252 | $validationError.ErrorContent = $ErrorText 253 | [System.Windows.Controls.Validation]::MarkInvalid($bindingExpressionBase,$validationError) 254 | } 255 | } 256 | } 257 | 258 | function Confirm-RequiredField { 259 | param ( 260 | $UI_Object = $this, 261 | $ErrorText = "This field is mandatory" 262 | ) 263 | if (!$UI_Object.Text) { 264 | Set-ValidationError -UIObject $UI_Object -ErrorText $ErrorText 265 | } 266 | else { 267 | Set-ValidationError -UIObject $UI_Object -ClearInvalid 268 | } 269 | } 270 | 271 | function Confirm-TextPatternField { 272 | param ( 273 | $UI_Object = $this, 274 | $ErrorText = "Invalid Value", 275 | [regex[]]$Regex 276 | ) 277 | $IsValid = $false 278 | foreach ($Pattern in $Regex) { 279 | if ($UI_Object.Text -match $Pattern) { 280 | $IsValid = $true 281 | break 282 | } 283 | } 284 | if ($IsValid){ 285 | Set-ValidationError -UIObject $UI_Object -ClearInvalid 286 | } 287 | else { 288 | Set-ValidationError -UIObject $UI_Object -ErrorText $ErrorText 289 | } 290 | } 291 | 292 | function Confirm-TextInput { 293 | param( 294 | $UI_Object = $this, 295 | $RegexPattern, 296 | [switch]$ToUpper 297 | ) 298 | $SelectionStart = $UI_Object.SelectionStart 299 | $TextLength = ($UI_Object.text).length 300 | $TmpArray = $UI_Object.text.ToCharArray() 301 | $Output = $TmpArray | ForEach-Object { $_ | Where-Object { $_ -match $RegexPattern } } 302 | $UI_Object.text = if($ToUpper) {(-join $Output).ToUpper()} else {(-join $Output)} 303 | if ( ($UI_Object.text).length -lt $TextLength ) { 304 | $UI_Object.SelectionStart = $SelectionStart - 1 305 | } else { $UI_Object.SelectionStart = $SelectionStart } 306 | } 307 | 308 | -------------------------------------------------------------------------------- /CommonTheme.ps1: -------------------------------------------------------------------------------- 1 | ########### 2 | # Learn how to build Material Design based PowerShell apps 3 | # 4 | # Common Functions and Assemblies related to Themes 5 | # 6 | # Avi Coren (c) 7 | # Blog - https://www.materialdesignps.com 8 | # Github - https://github.com/DrHalfBaked/PowerShell.MaterialDesign 9 | # LinkedIn - https://www.linkedin.com/in/avi-coren-6647b2105/ 10 | # 11 | # Last file update: Dec 23, 2021 04:30 12 | # 13 | 14 | [System.Collections.ArrayList]$ThemePrimaryColors = [System.Enum]::GetNames([MaterialDesignColors.PrimaryColor]) 15 | $ThemePrimaryColors.Sort() 16 | [System.Collections.ArrayList]$ThemeSecondaryColors = [System.Enum]::GetNames([MaterialDesignColors.SecondaryColor]) 17 | $ThemeSecondaryColors.Sort() 18 | 19 | 20 | 21 | # Set-Theme - Sets the window theme colors and mode 22 | # Get-ThemeMode - Returns the given app window theme mode ("Dark" or "Light") 23 | # Get-SystemTheme - Will return "Dark" or "Light" based on the current apps theme mode set in windows OS 24 | 25 | function Set-Theme { 26 | param( 27 | $Window, 28 | $PrimaryColor, 29 | $SecondaryColor, 30 | [Parameter()] 31 | [ValidateSet('Dark', 'Light')] 32 | $ThemeMode 33 | ) 34 | $Theme = [MaterialDesignThemes.Wpf.ResourceDictionaryExtensions]::GetTheme($Window.Resources) 35 | if($PrimaryColor) { 36 | $PrimaryColorObj = [MaterialDesignColors.SwatchHelper]::Lookup[$PrimaryColor] 37 | [void][MaterialDesignThemes.Wpf.ThemeExtensions]::SetPrimaryColor($Theme, $PrimaryColorObj) 38 | } 39 | if($SecondaryColor) { 40 | $SecondaryColorObj = [MaterialDesignColors.SwatchHelper]::Lookup[$SecondaryColor] 41 | [void][MaterialDesignThemes.Wpf.ThemeExtensions]::SetSecondaryColor($Theme, $SecondaryColorObj) 42 | } 43 | if($ThemeMode) { 44 | [void][MaterialDesignThemes.Wpf.ThemeExtensions]::SetBaseTheme($Theme, [MaterialDesignThemes.Wpf.Theme]::$ThemeMode) 45 | } 46 | [void][MaterialDesignThemes.Wpf.ResourceDictionaryExtensions]::SetTheme($Window.Resources, $Theme) 47 | } 48 | 49 | function Get-ThemeMode { 50 | param( 51 | $Window 52 | ) 53 | $Theme = [MaterialDesignThemes.Wpf.ResourceDictionaryExtensions]::GetTheme($Window.Resources) 54 | return [MaterialDesignThemes.Wpf.ThemeExtensions]::GetBaseTheme($Theme) 55 | } 56 | 57 | function Get-SystemTheme { 58 | return [MaterialDesignThemes.Wpf.Theme]::GetSystemTheme() 59 | } -------------------------------------------------------------------------------- /Content of Examples.txt: -------------------------------------------------------------------------------- 1 | Example1 - Input text to top textbox then button click displays text in the bottom textbox {change textbox to an outlined field} 2 | Example2 - Open and Save Dialog boxes. Floating Mini Buttons, OutlinedTextBox 3 | Example3 - SnackBars {move the xaml snackbar around to show that its at the bottom and when in stackpanel it pushes items. finally put it in a DockPanel below the stackpanel (with margin) and show the opacity problem} 4 | Example4 - DataTable / DataGrid {Task: Add a refresh button to get new data, text has no validation yet} 5 | Example5 - 6 | Example6 - Tab Control (Navigation Rails) 7 | Example7 - Tab Control (Navigation Rails) with popup box and left drawer 8 | Example8 - Tab awareness + introducing common files 9 | Example9 - Forms 10 | Example9b - Forms with input validation 11 | Example10 - Multiple DialogBoxes? 12 | Example11 - Context menu in TextBox 13 | Example12 - 14 | Example13 - Introducing Theme 15 | Example14 - 16 | Example15 - The Spinner and Runspace 17 | Example16 - 18 | Example17 - DataTable With "Gmail-like" controls 19 | 20 | 21 | -------------------------------------------------------------------------------- /Example.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Light 6 | Purple 7 | Amber 8 | 9 | 10 | 900 11 | 1427 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Example1.ps1: -------------------------------------------------------------------------------- 1 | ########### 2 | # Learn how to build Material Design based PowerShell apps 3 | # -------------------- 4 | # Example1: Hello World 5 | # -------------------- 6 | # Avi Coren (c) 7 | # Blog - https://www.materialdesignps.com 8 | # Github - https://github.com/DrHalfBaked/PowerShell.MaterialDesign 9 | # LinkedIn - https://www.linkedin.com/in/avi-coren-6647b2105/ 10 | # 11 | [Void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework') 12 | [Void][System.Reflection.Assembly]::LoadFrom("$PSScriptRoot\Assembly\MaterialDesignThemes.Wpf.dll") 13 | [Void][System.Reflection.Assembly]::LoadFrom("$PSScriptRoot\Assembly\MaterialDesignColors.dll") 14 | 15 | try { 16 | [xml]$Xaml = (Get-content "$PSScriptRoot\Example1.xaml") 17 | $Reader = New-Object System.Xml.XmlNodeReader $Xaml 18 | $Window = [Windows.Markup.XamlReader]::Load($Reader) 19 | } 20 | catch { 21 | Write-Error "Error building Xaml data.`n$_" 22 | exit 23 | } 24 | 25 | $Xaml.SelectNodes("//*[@Name]") | ForEach-Object { Set-Variable -Name ($_.Name) -Value $Window.FindName($_.Name) -Scope Script } 26 | 27 | $Btn1.Add_Click({$TxtBox2.Text = $TxtBox1.Text}) 28 | 29 | 30 | $Window.ShowDialog() | out-null -------------------------------------------------------------------------------- /Example1.xaml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 36 | 39 | 40 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /Example13.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Light 6 | LightBlue 7 | Indigo 8 | 9 | 10 | -------------------------------------------------------------------------------- /Example13.ps1: -------------------------------------------------------------------------------- 1 | ########### 2 | # Learn how to build Material Design based PowerShell apps 3 | # -------------------- 4 | # Example13: Introducing Theme 5 | # -------------------- 6 | # Avi Coren (c) 7 | # Blog - https://www.materialdesignps.com 8 | # Github - https://github.com/DrHalfBaked/PowerShell.MaterialDesign 9 | # LinkedIn - https://www.linkedin.com/in/avi-coren-6647b2105/ 10 | # 11 | Get-ChildItem -Path $PSScriptRoot -Filter Common*.PS1 | ForEach-Object {. ($_.FullName)} 12 | 13 | $Window = New-Window -XamlFile "$PSScriptRoot\Example13.xaml" 14 | $ConfigFilePath = "$PSScriptRoot\Example13.config" 15 | $ConfigXML = Open-File -Path $ConfigFilePath -FileType xml 16 | 17 | Set-Theme -Window $Window -PrimaryColor $ConfigXML.Parameters.Settings.Theme.PrimaryColor -SecondaryColor $ConfigXML.Parameters.Settings.Theme.SecondaryColor -ThemeMode $ConfigXML.Parameters.Settings.Theme.Mode 18 | 19 | $LeftDrawer_PrimaryColor_LstBox.Itemssource = $ThemePrimaryColors 20 | $LeftDrawer_SecondaryColor_LstBox.Itemssource = $ThemeSecondaryColors 21 | $LeftDrawer_ThemeMode_TglBtn.IsChecked = if((Get-ThemeMode -Window $Window) -eq "Dark") {$true} else {$false} 22 | 23 | [scriptblock]$OnClosingLeftDrawer = { 24 | $DrawerHost.IsLeftDrawerOpen = $false 25 | $LeftDrawer_Open_TglBtn.IsChecked = $false 26 | $LeftDrawer_Open_TglBtn.Visibility="Visible" 27 | } 28 | 29 | $DrawerHost.add_DrawerClosing($OnClosingLeftDrawer) 30 | 31 | $LeftDrawer_Close_TglBtn.add_Click($OnClosingLeftDrawer) 32 | 33 | $LeftDrawer_Open_TglBtn.add_Click({ 34 | $DrawerHost.IsLeftDrawerOpen = $true 35 | $LeftDrawer_Close_TglBtn.IsChecked = $true 36 | $LeftDrawer_Open_TglBtn.Visibility="Hidden" 37 | }) 38 | 39 | $LeftDrawer_ThemeMode_TglBtn.Add_Click({ 40 | $ThemeMode = if ($LeftDrawer_ThemeMode_TglBtn.IsChecked -eq $true) {"Dark"} else {"Light"} 41 | Set-Theme -Window $Window -ThemeMode $ThemeMode 42 | }) 43 | 44 | $LeftDrawer_PrimaryColor_LstBox.Add_SelectionChanged( { 45 | if ($this.IsMouseCaptured ) { # this condition prvents the event to be triggered when listbox selection is changed programatically 46 | Set-Theme -Window $Window -PrimaryColor $LeftDrawer_PrimaryColor_LstBox.SelectedValue 47 | } 48 | }) 49 | 50 | $LeftDrawer_SecondaryColor_LstBox.Add_SelectionChanged( { 51 | if ($this.IsMouseCaptured ) { # this condition prvents the event to be triggered when listbox selection is changed programatically 52 | Set-Theme -Window $Window -SecondaryColor $LeftDrawer_SecondaryColor_LstBox.SelectedValue 53 | } 54 | }) 55 | 56 | $LeftDrawer_Theme_Undo_Btn.Add_Click( { 57 | Set-Theme -Window $Window -PrimaryColor $ConfigXML.Parameters.Settings.Theme.PrimaryColor -SecondaryColor $ConfigXML.Parameters.Settings.Theme.SecondaryColor -ThemeMode $ConfigXML.Parameters.Settings.Theme.Mode 58 | $LeftDrawer_ThemeMode_TglBtn.IsChecked = if((Get-ThemeMode -Window $Window) -eq "Dark") {$true} else {$false} 59 | $LeftDrawer_PrimaryColor_LstBox.SelectedIndex = $ThemePrimaryColors.indexof($ConfigXML.Parameters.Settings.Theme.PrimaryColor) 60 | $LeftDrawer_SecondaryColor_LstBox.SelectedIndex = $ThemeSecondaryColors.indexof($ConfigXML.Parameters.Settings.Theme.SecondaryColor) 61 | }) 62 | 63 | $LeftDrawer_Theme_Apply_Btn.Add_Click( { 64 | 65 | $IsChanged = $false 66 | if (($LeftDrawer_PrimaryColor_LstBox.SelectedValue) -and $ConfigXML.Parameters.Settings.Theme.PrimaryColor -ne $LeftDrawer_PrimaryColor_LstBox.SelectedValue) { 67 | $IsChanged = $true 68 | $ConfigXML.Parameters.Settings.Theme.PrimaryColor = $LeftDrawer_PrimaryColor_LstBox.SelectedValue 69 | } 70 | if (($LeftDrawer_SecondaryColor_LstBox.SelectedValue) -and $ConfigXML.Parameters.Settings.Theme.SecondaryColor -ne $LeftDrawer_SecondaryColor_LstBox.SelectedValue) { 71 | $IsChanged = $true 72 | $ConfigXML.Parameters.Settings.Theme.SecondaryColor = $LeftDrawer_SecondaryColor_LstBox.SelectedValue 73 | } 74 | if (($ConfigXML.Parameters.Settings.Theme.Mode -eq "Light") -and ($LeftDrawer_ThemeMode_TglBtn.IsChecked)) { 75 | $IsChanged = $true 76 | $ConfigXML.Parameters.Settings.Theme.Mode = "Dark" 77 | } 78 | if (($ConfigXML.Parameters.Settings.Theme.Mode -eq "Dark") -and (!$LeftDrawer_ThemeMode_TglBtn.IsChecked)) { 79 | $IsChanged = $true 80 | $ConfigXML.Parameters.Settings.Theme.Mode = "Light" 81 | } 82 | if ($IsChanged) { 83 | try { 84 | $ConfigXML.Save($ConfigFilePath) 85 | New-Snackbar -Snackbar $MainSnackbar -Text "Theme was successfully saved" 86 | } 87 | catch { 88 | New-Snackbar -Snackbar $MainSnackbar -Text $_[0] -ButtonCaption "OK" 89 | return 90 | } 91 | } 92 | }) 93 | 94 | 95 | $Window.ShowDialog() | out-null -------------------------------------------------------------------------------- /Example13.xaml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 50 | 51 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | Light 75 | 76 | Dark 77 | 78 | 79 | 81 | 82 | 83 | 85 | 86 | 87 | 88 | 91 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 108 | 109 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /Example15.ps1: -------------------------------------------------------------------------------- 1 | ########### 2 | # Learn how to build Material Design based PowerShell apps 3 | # -------------------- 4 | # Example15: Spinner and runspace 5 | # -------------------- 6 | # Avi Coren (c) 7 | # Blog - https://www.materialdesignps.com 8 | # Github - https://github.com/DrHalfBaked/PowerShell.MaterialDesign 9 | # LinkedIn - https://www.linkedin.com/in/avi-coren-6647b2105/ 10 | # 11 | Get-ChildItem -Path $PSScriptRoot -Filter Common*.PS1 | ForEach-Object {. ($_.FullName)} 12 | 13 | $Window = New-Window -XamlFile "$PSScriptRoot\Example15.xaml" 14 | $TextBox_Output.AppendText("Main Runspace ID: $(([System.Management.Automation.Runspaces.Runspace]::DefaultRunSpace).id)`n") 15 | 16 | $Btn_StartJob.Add_Click({ 17 | $ApplicationLayer.IsEnabled = $false 18 | $SpinnerOverlayLayer.Visibility = "Visible" 19 | 20 | $Global:SyncHash = [hashtable]::Synchronized(@{ 21 | Window = $window 22 | SpinnerOverlayLayer = $SpinnerOverlayLayer 23 | TextBox_Output = $TextBox_Output 24 | ApplicationLayer = $ApplicationLayer 25 | }) 26 | $Runspace = [runspacefactory]::CreateRunspace() 27 | $Runspace.ThreadOptions = "ReuseThread" 28 | $Runspace.ApartmentState = "STA" 29 | $Runspace.Open() 30 | $Runspace.SessionStateProxy.SetVariable("SyncHash", $SyncHash) 31 | $Worker = [PowerShell]::Create().AddScript({ 32 | $RunspaceID = ([System.Management.Automation.Runspaces.Runspace]::DefaultRunSpace).id 33 | $SyncHash.Window.Dispatcher.Invoke([action]{$SyncHash.TextBox_Output.AppendText("New Runspace ID: $RunspaceID`n")}, "Normal") 34 | $Results = [System.Text.StringBuilder]::new() 35 | foreach ($number in 1..10000000) { 36 | if (($number % 2560583 ) -eq 0) { 37 | [void]$Results.AppendLine($number) 38 | } 39 | } 40 | if($Results){ 41 | $SyncHash.Window.Dispatcher.Invoke([action]{$SyncHash.TextBox_Output.AppendText($Results.ToString())}, "Normal") 42 | } 43 | $SyncHash.Window.Dispatcher.Invoke([action]{ $SyncHash.SpinnerOverlayLayer.Visibility = "Collapsed" }, "Normal") 44 | $SyncHash.Window.Dispatcher.Invoke([action]{ $SyncHash.ApplicationLayer.IsEnabled = $true }, "Normal") 45 | 46 | }) 47 | $Worker.Runspace = $Runspace 48 | 49 | Register-ObjectEvent -InputObject $Worker -EventName InvocationStateChanged -Action { 50 | param([System.Management.Automation.PowerShell] $ps) 51 | $state = $EventArgs.InvocationStateInfo.State 52 | if ($state -in 'Completed', 'Failed') { 53 | $ps.EndInvoke($Worker) 54 | $ps.Runspace.Dispose() 55 | $ps.Dispose() 56 | [GC]::Collect() 57 | } 58 | } | Out-Null 59 | 60 | Register-ObjectEvent -InputObject $Runspace -EventName AvailabilityChanged -Action { 61 | if ($($EventArgs.RunspaceAvailability) -eq 'Available'){ 62 | $Runspace.Dispose() 63 | [GC]::Collect() 64 | } 65 | } | Out-Null 66 | 67 | $Worker.BeginInvoke() 68 | 69 | }) 70 | 71 | $Window.ShowDialog() | out-null -------------------------------------------------------------------------------- /Example15.xaml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /Example2.ps1: -------------------------------------------------------------------------------- 1 | ########### 2 | # Learn how to build Material Design based PowerShell apps 3 | # -------------------- 4 | # Example2: Open and Save Dialog boxes 5 | # -------------------- 6 | # Avi Coren (c) 7 | # Blog - https://www.materialdesignps.com 8 | # Github - https://github.com/DrHalfBaked/PowerShell.MaterialDesign 9 | # LinkedIn - https://www.linkedin.com/in/avi-coren-6647b2105/ 10 | # 11 | [Void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework') 12 | [Void][System.Reflection.Assembly]::LoadFrom("$PSScriptRoot\Assembly\MaterialDesignThemes.Wpf.dll") 13 | [Void][System.Reflection.Assembly]::LoadFrom("$PSScriptRoot\Assembly\MaterialDesignColors.dll") 14 | 15 | try { 16 | [xml]$Xaml = (Get-content "$PSScriptRoot\Example2.xaml") 17 | $Reader = New-Object System.Xml.XmlNodeReader $Xaml 18 | $Window = [Windows.Markup.XamlReader]::Load($Reader) 19 | } 20 | catch { 21 | Write-Error "Error building Xaml data.`n$_" 22 | exit 23 | } 24 | 25 | $Xaml.SelectNodes("//*[@Name]") | ForEach-Object { Set-Variable -Name ($_.Name) -Value $Window.FindName($_.Name) -Scope Script } 26 | 27 | $InitialDirectory = "$([Environment]::GetFolderPath("MyDocuments"))" 28 | $FileFilter = "Text files|*.txt|All Files|*.*" 29 | 30 | function Save-File { 31 | Param ( 32 | [string] $InitialDirectory, 33 | [string] $Filter 34 | ) 35 | try { 36 | $SaveFileDialog = New-Object Microsoft.Win32.SaveFileDialog 37 | $SaveFileDialog.initialDirectory = $initialDirectory 38 | $SaveFileDialog.filter = $Filter 39 | $SaveFileDialog.CreatePrompt = $False; 40 | $SaveFileDialog.OverwritePrompt = $True; 41 | $SaveFileDialog.ShowDialog() | Out-Null 42 | return $SaveFileDialog.filename 43 | } 44 | catch { 45 | Throw "Save-File Error $_" 46 | } 47 | } 48 | 49 | function Open-File { 50 | Param ( 51 | [string] $InitialDirectory, 52 | [string] $Filter 53 | ) 54 | try{ 55 | $OpenFileDialog = New-Object Microsoft.Win32.OpenFileDialog 56 | $OpenFileDialog.initialDirectory = $initialDirectory 57 | $OpenFileDialog.filter = $Filter 58 | # Examples of other common filters: "Word Documents|*.doc|Excel Worksheets|*.xls|PowerPoint Presentations|*.ppt |Office Files|*.doc;*.xls;*.ppt |All Files|*.*" 59 | $OpenFileDialog.ShowDialog() | Out-Null 60 | return $OpenFileDialog.filename 61 | } 62 | catch { 63 | Throw "Open-File Error $_" 64 | } 65 | } 66 | 67 | $Btn_OpenFile.Add_Click({ On_OpenFile }) 68 | $Btn_SaveFile.Add_Click({ On_SaveFile }) 69 | 70 | Function On_OpenFile { 71 | $OpenedFile = Open-File -InitialDirectory $InitialDirectory -Filter $FileFilter 72 | if ($OpenedFile) { 73 | $TextBox_Editor.Text = Get-content $OpenedFile -Raw 74 | } 75 | } 76 | 77 | Function On_SaveFile { 78 | $SavePath = Save-File -InitialDirectory $InitialDirectory -Filter $FileFilter 79 | if ($SavePath) { 80 | $TextBox_Editor.Text | Out-File -FilePath $SavePath -Encoding UTF8 81 | } 82 | } 83 | 84 | 85 | $Window.ShowDialog() | out-null -------------------------------------------------------------------------------- /Example2.xaml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 36 | 39 | 40 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /Example3.ps1: -------------------------------------------------------------------------------- 1 | ########### 2 | # Learn how to build Material Design based PowerShell apps 3 | # -------------------- 4 | # Example3: SnackBars 5 | # -------------------- 6 | # Avi Coren (c) 7 | # Blog - https://www.materialdesignps.com 8 | # Github - https://github.com/DrHalfBaked/PowerShell.MaterialDesign 9 | # LinkedIn - https://www.linkedin.com/in/avi-coren-6647b2105/ 10 | # 11 | [Void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework') 12 | [Void][System.Reflection.Assembly]::LoadFrom("$PSScriptRoot\Assembly\MaterialDesignThemes.Wpf.dll") 13 | [Void][System.Reflection.Assembly]::LoadFrom("$PSScriptRoot\Assembly\MaterialDesignColors.dll") 14 | 15 | try { 16 | [xml]$Xaml = (Get-content "$PSScriptRoot\Example3.xaml") 17 | $Reader = New-Object System.Xml.XmlNodeReader $Xaml 18 | $Window = [Windows.Markup.XamlReader]::Load($Reader) 19 | } 20 | catch { 21 | Write-Error "Error building Xaml data.`n$_" 22 | exit 23 | } 24 | 25 | $Xaml.SelectNodes("//*[@Name]") | ForEach-Object { Set-Variable -Name ($_.Name) -Value $Window.FindName($_.Name) -Scope Script } 26 | 27 | 28 | $MessageQueue = [MaterialDesignThemes.Wpf.SnackbarMessageQueue]::new() 29 | $MessageQueue.DiscardDuplicates = $true 30 | 31 | function New-Snackbar { 32 | param ( 33 | $Snackbar, 34 | $Text, 35 | $ButtonCaption 36 | ) 37 | if ($ButtonCaption) { 38 | $MessageQueue.Enqueue($Text, $ButtonCaption, {$null}, $null, $false, $false, [TimeSpan]::FromHours( 9999 )) 39 | # 7 Arguments of Enqueue: content, actionContent, actionHandler, actionArgument, promote, neverConsiderToBeDuplicate, durationOverride 40 | } 41 | else { 42 | $MessageQueue.Enqueue($Text, $null, $null, $null, $false, $false, $null) 43 | } 44 | $Snackbar.MessageQueue = $MessageQueue 45 | } 46 | 47 | $Btn_ShowSnkBarNoHide.Add_Click({New-Snackbar -Snackbar $Snackbar1 -Text $TxtBox_SnkBarContent.Text -ButtonCaption "OK"}) 48 | $Btn_ShowSnkBarAutoHide.Add_Click({New-Snackbar -Snackbar $Snackbar1 -Text $TxtBox_SnkBarContent.Text}) 49 | 50 | $Window.ShowDialog() | out-null -------------------------------------------------------------------------------- /Example3.xaml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 207 | 210 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | -------------------------------------------------------------------------------- /Example9b.ps1: -------------------------------------------------------------------------------- 1 | ########### 2 | # Learn how to build Material Design based PowerShell apps 3 | # -------------------- 4 | # Example9b: Forms with validations 5 | # -------------------- 6 | # Avi Coren (c) 7 | # Blog - https://www.materialdesignps.com 8 | # Github - https://github.com/DrHalfBaked/PowerShell.MaterialDesign 9 | # LinkedIn - https://www.linkedin.com/in/avi-coren-6647b2105/ 10 | # 11 | Get-ChildItem -Path $PSScriptRoot -Filter Common*.PS1 | ForEach-Object {. ($_.FullName)} 12 | 13 | $Window = New-Window -XamlFile "$PSScriptRoot\Example9b.xaml" 14 | Set-CurrentCulture 15 | 16 | Get-Variable -Include "Car_Reg_Form_Textbox*","Car_Reg_Form_Combobox*","Car_Reg_Form_*Picker*" -ValueOnly | 17 | ForEach-Object { Set-OutlinedProperty -InputObject $_ -Padding "8" -FloatingOffset "1,-18" -FloatingScale "0.8" -Opacity "0.75" -FontSize 16 } 18 | $CarList = Import-Csv -Path "$PSScriptRoot\Cars.csv" 19 | $Car_Reg_Form_Combobox_Make.ItemsSource = ($CarList.Make | Select-Object -Unique | Sort-Object ) 20 | $Car_Reg_Form_Combobox_Color.ItemsSource = ([System.Windows.Media.Colors].Getproperties() | Select-Object -ExpandProperty name | Sort-Object ) 21 | $Car_Reg_Form_Combobox_Year.ItemsSource = (1990..2021) 22 | $Car_Reg_Form_Textbox_Note.SpellCheck.IsEnabled = $true 23 | $Car_Reg_Form_Textbox_Owner.SpellCheck.IsEnabled = $true 24 | 25 | $Car_Reg_Form_Combobox_Make.add_SelectionChanged({ 26 | $Car_Reg_Form_Combobox_Model.ItemsSource = $null 27 | $Car_Reg_Form_Combobox_Model.ItemsSource = ($CarList | Where-Object {$_.Make -eq $Car_Reg_Form_Combobox_Make.SelectedItem } | Select-Object -ExpandProperty Model | Select-Object -Unique | Sort-Object ) 28 | }) 29 | 30 | [scriptblock]$OnResetCarForm = { 31 | Get-Variable -Include "Car_Reg_Form_Combobox*" -ValueOnly | ForEach-Object {$_.SelectedItem = $null} 32 | Get-Variable -Include "Car_Reg_Form_Textbox*","Car_Reg_Form_*Picker*" -ValueOnly | ForEach-Object { $_.Text = $null } 33 | $Car_Reg_Form_RatingBar_Rate.Value = 0 34 | Get-Variable -Include "Car_Reg_Form_Textbox*","Car_Reg_Form_Combobox*","Car_Reg_Form_*Picker*" -ValueOnly | ForEach-Object {Set-ValidationError -UIObject $_ -ClearInvalid} 35 | } 36 | 37 | $Car_Reg_Form_Btn_Reset.add_Click($OnResetCarForm) 38 | $Car_Reg_Form_Btn_Cancel.add_Click({ 39 | Invoke-Command -Command $OnResetCarForm 40 | Set-NavigationRailTab -NavigationRail $NavRail -TabName "Cars" 41 | }) 42 | $Car_Reg_Form_Btn_Apply.add_Click({ 43 | $FormHasErrors = $false 44 | Get-Variable -Include "Car_Reg_Form_Combobox*","Car_Reg_Form_*Picker*","Car_Reg_Form_Textbox_Owner","Car_Reg_Form_Textbox_Plate" -ValueOnly | ForEach-Object { Confirm-RequiredField -UI_Object $_ } 45 | Confirm-TextPatternField -UI_Object $Car_Reg_Form_Textbox_Plate -Regex '^[0-9]{2}-[0-9]{3}-[0-9]{2}$','^[0-9]{3}-[0-9]{2}-[0-9]{3}$' -ErrorText "Invalid plate number" 46 | Get-Variable -Include "Car_Reg_Form_Combobox*","Car_Reg_Form_*Picker*","Car_Reg_Form_Textbox_Owner","Car_Reg_Form_Textbox_Plate" -ValueOnly | ForEach-Object { 47 | if (Set-ValidationError -UIObject $_ -CheckHasError) { 48 | $FormHasErrors = $true 49 | } 50 | } 51 | if ($FormHasErrors){ 52 | return 53 | } 54 | 55 | $RowContent = @( 56 | $Car_Reg_Form_Textbox_Plate.Text 57 | $Car_Reg_Form_Combobox_Make.SelectedItem 58 | $Car_Reg_Form_Combobox_Model.SelectedItem 59 | $Car_Reg_Form_Combobox_Year.SelectedItem 60 | $Car_Reg_Form_Textbox_Owner.Text 61 | $Car_Reg_Form_Combobox_Color.SelectedItem 62 | $Car_Reg_Form_Textbox_Note.Text 63 | $Car_Reg_Form_RatingBar_Rate.Value 64 | $Car_Reg_Form_DatePicker_Registered.Text 65 | $Car_Reg_Form_TimePicker_Registered.Text 66 | ) 67 | [void]$Cars_Datatable.Rows.Add($RowContent) 68 | Invoke-Command -Command $OnResetCarForm 69 | Set-NavigationRailTab -NavigationRail $NavRail -TabName "Cars" 70 | }) 71 | 72 | $Cars_Datatable = [System.Data.DataTable]::New() 73 | [void]$Cars_Datatable.Columns.AddRange(@('Plate', 'Make', 'Model', 'Year', 'Owner', 'Color', 'Note', 'Rating', 'DateReg', 'TimeReg')) 74 | $Cars_Datatable.primarykey = $Cars_Datatable.columns['Plate'] 75 | $Cars_DataGrid.ItemsSource = $Cars_Datatable.DefaultView 76 | 77 | $Cars_Popup_Add_Car.Add_Click({ Set-NavigationRailTab -NavigationRail $NavRail -TabName "CarRegistration" }) 78 | 79 | [scriptblock]$OnClosingDrawer = { 80 | $DrawerHost.IsLeftDrawerOpen = $false 81 | $TglBtn_OpenLeftDrawer.IsChecked = $false 82 | $TglBtn_OpenLeftDrawer.Visibility="Visible" 83 | } 84 | 85 | $DrawerHost.add_DrawerClosing($OnClosingDrawer) 86 | $TglBtn_CloseLeftDrawer.add_Click($OnClosingDrawer) 87 | 88 | $TglBtn_OpenLeftDrawer.add_Click({ 89 | $DrawerHost.IsLeftDrawerOpen = $true 90 | $TglBtn_CloseLeftDrawer.IsChecked = $true 91 | $TglBtn_OpenLeftDrawer.Visibility="Hidden" 92 | }) 93 | 94 | $NavRail.add_SelectionChanged({ 95 | if ($_.Source -like "System.Windows.Controls.TabControl*") { 96 | switch (Get-NavigationRailSelectedTabName -NavigationRail $NavRail) { 97 | "Users" { } 98 | "Cars" { } 99 | "CarRegistration" { Invoke-Command -command $OnResetCarForm } 100 | "Photos" { } 101 | "Movies" { } 102 | } 103 | } 104 | }) 105 | 106 | $Car_Reg_Form_TextBox_Plate.add_TextChanged( { 107 | Confirm-TextInput -RegexPattern $RegEx_NumbersDash 108 | }) 109 | 110 | $Car_Reg_Form_TextBox_Owner.add_TextChanged( { 111 | Confirm-TextInput -RegexPattern $RegEx_LettersSpace -ToUpper 112 | }) 113 | 114 | $Car_Reg_Form_Textbox_Note.add_TextChanged( { 115 | Confirm-TextInput -RegexPattern $RegEx_NoteChars 116 | }) 117 | 118 | $Car_Reg_Form_TextBox_Plate.add_LostFocus({ 119 | Confirm-TextPatternField -Regex '^[0-9]{2}-[0-9]{3}-[0-9]{2}$','^[0-9]{3}-[0-9]{2}-[0-9]{3}$' -ErrorText "Invalid plate number" 120 | }) 121 | 122 | $Car_Reg_Form_TimePicker_Registered.add_SelectedTimeChanged({ Confirm-RequiredField }) 123 | $Car_Reg_Form_DatePicker_Registered.add_SelectedDateChanged({ Confirm-RequiredField }) 124 | Get-Variable -Include "Car_Reg_Form_Combobox*","Car_Reg_Form_TextBox_Owner","Car_Reg_Form_TimePicker_Registered","Car_Reg_Form_DatePicker_Registered" -ValueOnly | 125 | ForEach-Object {$_.add_LostFocus({ Confirm-RequiredField })} 126 | Get-Variable -Include "Car_Reg_Form_TextBox_Plate","Car_Reg_Form_TextBox_Owner" -ValueOnly | 127 | ForEach-Object {$_.add_TextChanged({ Confirm-RequiredField })} 128 | 129 | $Window.ShowDialog() | out-null -------------------------------------------------------------------------------- /Example9b.xaml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 60 | 61 | 62 | 63 | 64 | 65 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 141 | 143 | 145 | 146 | 148 | 151 | 152 | 155 | 157 | 158 | 162 | 164 | 166 | 167 | 170 | 171 | 172 | 223 | 226 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PowerShell WPF apps, based on Material Design style 2 | This repository holds PowerShell scripts, implementing Material Design style for WPF apps. 3 | 4 | They are all part of my blog site https://avicoren.wixsite.com/powershell 5 | 6 | All of the GUI components are based on MDIX project found on this repo: 7 | 8 | https://github.com/MaterialDesignInXAML/MaterialDesignInXamlToolkit 9 | -------------------------------------------------------------------------------- /Resources/Images/mr_bean.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrHalfBaked/PowerShell.MaterialDesign/e53a8b2c2e8e28a7c5c40d15fac4cb78b562d00b/Resources/Images/mr_bean.jpg -------------------------------------------------------------------------------- /Resources/Images/mr_bean_tiny.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrHalfBaked/PowerShell.MaterialDesign/e53a8b2c2e8e28a7c5c40d15fac4cb78b562d00b/Resources/Images/mr_bean_tiny.jpg -------------------------------------------------------------------------------- /cars.csv: -------------------------------------------------------------------------------- 1 | Make,Model 2 | Audi,A3 3 | Audi,A5 4 | Audi,Q7 5 | Audi,A4 6 | Nissan,370Z 7 | Maybach,Landaulet 8 | Audi,Q5 9 | Nissan,Cube 10 | Hyundai,Elantra 11 | Nissan,Pathfinder 12 | Infiniti,EX 13 | Infiniti,M 14 | Infiniti,G37 15 | BMW,7 16 | Lotus,Elise 17 | Lotus,Exige 18 | Chevrolet,Silverado 19 | BMW,X5 20 | BMW,X6 21 | Chevrolet,Colorado 22 | Chevrolet,Express 23 | Chevrolet,Silverado 24 | Nissan,370Z 25 | Volvo,C30 26 | Bentley,Brooklands 27 | Bentley,Continental 28 | Volvo,C70 29 | Volvo,S40 30 | Volvo,S80 31 | Volvo,V50 32 | Volvo,XC60 33 | Volvo,XC70 34 | Volvo,XC90 35 | Volvo,V70 36 | Toyota,4Runner 37 | Honda,Accord 38 | Audi,A3 39 | Audi,A4 40 | Toyota,Avalon 41 | Ford,Focus 42 | Nissan,Altima 43 | Toyota,Camry 44 | Bentley,Azure 45 | Rolls-Royce,Ghost 46 | Audi,A5 47 | Rolls-Royce,Phantom 48 | Toyota,Corolla 49 | Volkswagen,Jetta 50 | Toyota,FJ 51 | Toyota,Highlander 52 | Toyota,Land 53 | Maybach,57 54 | Maybach,62 55 | Maybach,Landaulet 56 | Toyota,Matrix 57 | Volkswagen,CC 58 | Audi,A6 59 | Nissan,Armada 60 | Audi,A8 61 | Nissan,Cube 62 | Audi,Q5 63 | Lamborghini,Gallardo 64 | Chevrolet,Aveo5 65 | Lexus,LS 66 | Hyundai,Accent 67 | Hyundai,Azera 68 | Audi,Q7 69 | Mercedes-Benz,C-Class 70 | BMW,1 71 | Hyundai,Elantra 72 | Ford,Fusion 73 | Kia,Forte 74 | Honda,Civic 75 | Kia,Optima 76 | Hyundai,Genesis 77 | Volkswagen,GTI 78 | Kia,Rio5 79 | Kia,Rio 80 | Ford,Mustang 81 | Kia,Soul 82 | Audi,R8 83 | Kia,Sedona 84 | Chevrolet,Camaro 85 | Volkswagen,Golf 86 | Audi,S4 87 | Kia,Sportage 88 | Hyundai,Santa 89 | Ford,Taurus 90 | Ford,Edge 91 | Audi,S5 92 | Audi,S6 93 | Chevrolet,Corvette 94 | Nissan,Pathfinder 95 | Volkswagen,Routan 96 | Volkswagen,Tiguan 97 | Hyundai,Sonata 98 | Hyundai,Veracruz 99 | Honda,Fit 100 | Mazda,CX-7 101 | Ford,Flex 102 | Volkswagen,Touareg 103 | Mercedes-Benz,CL-Class 104 | Hyundai,Tucson 105 | Mercedes-Benz,CLS-Class 106 | Mitsubishi,Eclipse 107 | Toyota,RAV4 108 | Mitsubishi,Endeavor 109 | Mitsubishi,Galant 110 | Mitsubishi,Lancer 111 | Cadillac,CTS-V 112 | Cadillac,CTS 113 | BMW,3 114 | Infiniti,EX 115 | Mercedes-Benz,E-Class 116 | Mercedes-Benz,G-Class 117 | Mitsubishi,Outlander 118 | Toyota,Sequoia 119 | Mercedes-Benz,GL-Class 120 | Nissan,Sentra 121 | Nissan,Versa 122 | Mercedes-Benz,GLK-Class 123 | Mercedes-Benz,R-Class 124 | Ford,Escape 125 | Cadillac,Escalade 126 | Dodge,Avenger 127 | Honda,CR-V 128 | Cadillac,DTS 129 | Cadillac,SRX 130 | Nissan,Xterra 131 | BMW,5 132 | Mercedes-Benz,M-Class 133 | Mercedes-Benz,SLK-Class 134 | Lincoln,MKS 135 | Lincoln,MKT 136 | Lincoln,MKX 137 | Lincoln,MKZ 138 | Mazda,CX-9 139 | Toyota,Sienna 140 | Honda,Element 141 | Mazda,Mazda3 142 | Mazda,Mazdaspeed3 143 | Ford,Explorer 144 | Mazda,Mazda5 145 | Lincoln,Navigator 146 | Lincoln,Town 147 | Infiniti,FX 148 | Dodge,Caliber 149 | BMW,6 150 | Infiniti,M 151 | Dodge,Challenger 152 | Cadillac,STS 153 | Mazda,Mazda6 154 | Dodge,Charger 155 | Ford,Expedition 156 | Mazda,MX-5 157 | Mazda,RX-8 158 | Toyota,Venza 159 | Toyota,Yaris 160 | Transit,Connect 161 | Ford,Crown 162 | Mazda,Tribute 163 | Jeep,Commander 164 | GMC,Acadia 165 | GMC,Terrain 166 | GMC,Canyon 167 | Infiniti,G37 168 | Honda,Pilot 169 | Dodge,Grand 170 | Jeep,Compass 171 | BMW,7 172 | Chevrolet,Equinox 173 | Dodge,Journey 174 | Lexus,ES 175 | Dodge,Nitro 176 | Porsche,911 177 | GMC,Yukon 178 | Infiniti,QX56 179 | Acura,MDX 180 | Acura,RDX 181 | BMW,M3 182 | Acura,ZDX 183 | Acura,RL 184 | Acura,TL 185 | Acura,TSX 186 | Dodge,Viper 187 | Porsche,Boxster 188 | Porsche,Cayenne 189 | Chevrolet,HHR 190 | Porsche,Cayman 191 | Chevrolet,Impala 192 | Buick,Enclave 193 | Buick,Lacrosse 194 | Suzuki,Grand 195 | GMC,Sierra 196 | Honda,Odyssey 197 | GMC,Savana 198 | Suzuki,Kizashi 199 | Saab,09-Mar 200 | Suzuki,SX4 201 | Subaru,Forester 202 | Lexus,GS 203 | Buick,Lucerne 204 | Aston,Martin 205 | Subaru,Impreza 206 | Jeep,Grand 207 | Land,Rover 208 | Jeep,Liberty 209 | Ferrari,612 210 | Chrysler,Sebring 211 | Scion,tC 212 | MINI,Cooper 213 | MINI,Clubman 214 | Jaguar,XK 215 | Chrysler,300 216 | Chrysler,Town 217 | Jaguar,XF 218 | Jeep,Patriot 219 | Lotus,Elise 220 | Chevrolet,Malibu 221 | Lotus,Exige 222 | Maserati,GranTurismo 223 | Jeep,Wrangler 224 | Maserati,Quattroporte 225 | Honda,Ridgeline 226 | Mercury,Grand 227 | BMW,M6 228 | BMW,X3 229 | Chevrolet,Suburban 230 | Chevrolet,Tahoe 231 | BMW,Z4 232 | Saab,09-May 233 | Mercury,Mariner 234 | Chevrolet,Traverse 235 | Mercury,Milan 236 | Chevrolet,Avalanche 237 | Dodge,Ram 238 | Lexus,IS 239 | Toyota,Tacoma 240 | Scion,xB 241 | Scion,xD 242 | Jaguar,XJ 243 | Subaru,Legacy 244 | Suzuki,Equator 245 | Subaru,Outback 246 | Nissan,Frontier 247 | Lexus,LX 248 | Ford,Ranger 249 | Toyota,Tundra 250 | Dodge,Dakota 251 | Nissan,Titan 252 | Ford,F-150 253 | BMW,X5 254 | BMW,X6 255 | Chevrolet,Colorado 256 | Chevrolet,Express 257 | Chevrolet,Silverado 258 | Nissan,370Z 259 | Volvo,C30 260 | Bentley,Continental 261 | Volvo,C70 262 | Volvo,S40 263 | Volvo,S60 264 | Volvo,S80 265 | Volvo,V50 266 | Volvo,XC60 267 | Volvo,XC70 268 | Toyota,4Runner 269 | Volvo,XC90 270 | Audi,A3 271 | Audi,A4 272 | Ford,Fiesta 273 | Honda,Accord 274 | Toyota,Avalon 275 | Toyota,Camry 276 | Ford,Focus 277 | Nissan,Altima 278 | Toyota,Corolla 279 | Audi,A5 280 | Rolls-Royce,Ghost 281 | Rolls-Royce,Phantom 282 | Volkswagen,Jetta 283 | Toyota,FJ 284 | Audi,A6 285 | Toyota,Highlander 286 | Toyota,Land 287 | Toyota,Matrix 288 | Maybach,57 289 | Maybach,62 290 | Maybach,Landaulet 291 | Nissan,Armada 292 | Chevrolet,Aveo 293 | Chevrolet,Aveo5 294 | Audi,A8 295 | Nissan,Cube 296 | Audi,Q5 297 | Honda,Civic 298 | Lamborghini,Gallardo 299 | Lexus,LS 300 | Hyundai,Accent 301 | Hyundai,Azera 302 | Audi,Q7 303 | Toyota,RAV4 304 | Nissan,Juke 305 | Chevrolet,Camaro 306 | Hyundai,Elantra 307 | Volkswagen,CC 308 | Ford,Fusion 309 | Kia,Forte 310 | Audi,R8 311 | Hyundai,Equus 312 | Kia,Optima 313 | Kia,Rio 314 | Hyundai,Genesis 315 | Volkswagen,GTI 316 | Ford,Mustang 317 | Mercedes-Benz,C-Class 318 | Kia,Rio5 319 | Kia,Soul 320 | Ford,Shelby 321 | Kia,Sedona 322 | Audi,S4 323 | Kia,Sorento 324 | Kia,Sportage 325 | Nissan,Pathfinder 326 | Hyundai,Santa 327 | Ford,Taurus 328 | Volkswagen,Golf 329 | Ford,Edge 330 | Audi,S5 331 | Audi,S6 332 | Chevrolet,Corvette 333 | Volkswagen,Routan 334 | Hyundai,Sonata 335 | Honda,CR-Z 336 | Hyundai,Veracruz 337 | Honda,Fit 338 | Mazda,CX-7 339 | Ford,Flex 340 | Hyundai,Tucson 341 | Mazda,CX-9 342 | Volkswagen,Tiguan 343 | BMW,1 344 | Mercedes-Benz,CL-Class 345 | Mercedes-Benz,CLS-Class 346 | Mitsubishi,Eclipse 347 | Mitsubishi,Endeavor 348 | Mitsubishi,Galant 349 | Cadillac,CTS-V 350 | Mitsubishi,Lancer 351 | Cadillac,CTS 352 | Toyota,Sequoia 353 | Mercedes-Benz,E-Class 354 | BMW,3 355 | Nissan,Sentra 356 | Mercedes-Benz,G-Class 357 | Cadillac,Escalade 358 | Mitsubishi,Outlander 359 | Cadillac,DTS 360 | Infiniti,EX 361 | Mercedes-Benz,GL-Class 362 | Nissan,Versa 363 | Mercedes-Benz,GLK-Class 364 | Ford,Escape 365 | Mercedes-Benz,R-Class 366 | Chevrolet,Cruze 367 | Cadillac,SRX 368 | Dodge,Avenger 369 | Honda,CR-V 370 | Honda,Element 371 | Nissan,Xterra 372 | Mercedes-Benz,M-Class 373 | Toyota,Sienna 374 | BMW,5 375 | Mercedes-Benz,SL-Class 376 | Mercedes-Benz,SLK-Class 377 | Lincoln,MKS 378 | Lincoln,MKT 379 | Lincoln,MKX 380 | Lincoln,MKZ 381 | Mazda,Mazda2 382 | Mazda,Mazda3 383 | Ford,Explorer 384 | Mazda,Mazdaspeed3 385 | Honda,Pilot 386 | Lincoln,Navigator 387 | Lincoln,Town 388 | Infiniti,FX 389 | Cadillac,STS 390 | Dodge,Caliber 391 | Dodge,Challenger 392 | Infiniti,M 393 | Toyota,Venza 394 | Ford,Expedition 395 | Dodge,Charger 396 | Mazda,Mazda6 397 | GMC,Acadia 398 | Dodge,Durango 399 | Mazda,MX-5 400 | Mazda,RX-8 401 | Infiniti,G25 402 | Toyota,Yaris 403 | Chevrolet,Equinox 404 | Transit,Connect 405 | Porsche,911 406 | Mazda,Tribute 407 | Dodge,Grand 408 | Jeep,Compass 409 | GMC,Canyon 410 | Dodge,Journey 411 | Infiniti,G37 412 | BMW,7 413 | BMW,ActiveHybrid 414 | Dodge,Nitro 415 | BMW,ALPINA 416 | Infiniti,IPL 417 | GMC,Terrain 418 | GMC,Yukon 419 | Infiniti,QX56 420 | Acura,MDX 421 | Acura,RDX 422 | Acura,ZDX 423 | BMW,M3 424 | Acura,RL 425 | Acura,TL 426 | Acura,TSX 427 | GMC,Savana 428 | Porsche,Boxster 429 | Porsche,Cayenne 430 | Chevrolet,HHR 431 | Porsche,Cayman 432 | Chevrolet,Impala 433 | Subaru,Forester 434 | Buick,Enclave 435 | Suzuki,Grand 436 | Buick,Lacrosse 437 | Honda,Odyssey 438 | Suzuki,Kizashi 439 | Saab,09-Mar 440 | Suzuki,SX4 441 | Lexus,ES 442 | Buick,Lucerne 443 | Buick,Regal 444 | Aston,Martin 445 | Jeep,Grand 446 | Subaru,Impreza 447 | Jeep,Liberty 448 | Land,Rover 449 | Chrysler,200 450 | Scion,tC 451 | MINI,Cooper 452 | Jaguar,XJ 453 | MINI,Clubman 454 | Jaguar,XK 455 | Chrysler,300 456 | Jaguar,XF 457 | Jeep,Patriot 458 | Chrysler,Town 459 | Lotus,Elise 460 | Chevrolet,Malibu 461 | Lotus,Evora 462 | MINI,Countryman 463 | Lotus,Exige 464 | Maserati,GranTurismo 465 | Maserati,Quattroporte 466 | Jeep,Wrangler 467 | Honda,Ridgeline 468 | Mercury,Grand 469 | Mercury,Mariner 470 | BMW,X3 471 | Chevrolet,Suburban 472 | Dodge,Ram 473 | GMC,Sierra 474 | Chevrolet,Tahoe 475 | BMW,Z4 476 | Saab,9-4X 477 | Saab,09-May 478 | Chevrolet,Traverse 479 | Mercury,Milan 480 | Lexus,GS 481 | Chevrolet,Avalanche 482 | Subaru,Legacy 483 | Lexus,IS 484 | Toyota,Tacoma 485 | Scion,xB 486 | Scion,xD 487 | Toyota,Tundra 488 | Suzuki,Equator 489 | Nissan,Frontier 490 | Subaru,Outback 491 | Ford,Ranger 492 | Lexus,LX 493 | Ford,E-150 494 | Ford,E-350 495 | Dodge,Dakota 496 | Nissan,Titan 497 | Ford,E-250 498 | Ford,F-150 499 | Acura,TL 500 | Chevrolet,Colorado 501 | Chevrolet,Express 502 | Bentley,Continental 503 | Volvo,S60 504 | Audi,A3 505 | Audi,A4 506 | Ford,Fiesta 507 | Ford,Focus 508 | Volvo,S80 509 | Volvo,XC60 510 | Volvo,XC70 511 | Volvo,XC90 512 | Audi,A5 513 | Audi,A6 514 | Audi,A7 515 | Audi,Q5 516 | Audi,Q7 517 | Hyundai,Accent 518 | Chevrolet,Camaro 519 | Hyundai,Elantra 520 | Ford,Fusion 521 | Audi,R8 522 | Hyundai,Genesis 523 | Ford,Mustang 524 | Kia,Sedona 525 | Kia,Sorento 526 | Audi,S4 527 | Kia,Sportage 528 | Ford,Taurus 529 | Audi,S5 530 | Ford,Edge 531 | Chevrolet,Corvette 532 | Hyundai,Sonata 533 | Hyundai,Tucson 534 | Ford,Flex 535 | Mitsubishi,Eclipse 536 | Ford,Escape 537 | Chevrolet,Cruze 538 | Nissan,Altima 539 | Nissan,Sentra 540 | Nissan,Versa 541 | Ford,Explorer 542 | Mazda,Mazda5 543 | Mazda,Mazda6 544 | Infiniti,M 545 | Chevrolet,Equinox 546 | Ford,Transit 547 | Toyota,Yaris 548 | Toyota,Highlander 549 | Chevrolet,Impala 550 | Subaru,Impreza 551 | Land,Rover 552 | Scion,tC 553 | MINI,Cooper 554 | Chevrolet,Malibu 555 | MINI,Clubman 556 | MINI,Countryman 557 | Chevrolet,Sonic 558 | Toyota,Camry 559 | Toyota,FJ 560 | Chevrolet,Traverse 561 | Scion,xB 562 | Aston,Martin 563 | Ford,E-150 564 | Buick,Enclave 565 | Ford,E-350 566 | Buick,Lacrosse 567 | Buick,Regal 568 | Ford,E-250 569 | Nissan,Titan 570 | BMW,1 571 | BMW,3 572 | Nissan,370Z 573 | Nissan,JUKE 574 | Hyundai,Veloster 575 | Hyundai,Equus 576 | Hyundai,Santa 577 | Ford,Expedition 578 | Nissan,Xterra 579 | Nissan,Pathfinder 580 | Hyundai,Veracruz 581 | Infiniti,G25 582 | Infiniti,G37 583 | Volvo,C30 584 | Jeep,Compass 585 | Nissan,Armada 586 | Lexus,IS 587 | Lexus,ES 588 | Lexus,LS 589 | Toyota,Sienna 590 | Audi,A8 591 | Audi,TT 592 | Honda,Accord 593 | Lexus,RX 594 | Infiniti,IPL 595 | Lexus,LFA 596 | Infiniti,EX 597 | Infiniti,FX 598 | Infiniti,QX56 599 | Dodge,Durango 600 | Jeep,Grand 601 | Toyota,4Runner 602 | Mazda,Mazda2 603 | Toyota,Sequoia 604 | Mazda,Mazda3 605 | Dodge,Charger 606 | Volkswagen,Tiguan 607 | Dodge,Challenger 608 | Dodge,Avenger 609 | Dodge,Caliber 610 | Volkswagen,Jetta 611 | Volkswagen,CC 612 | Mazda,Mazdaspeed3 613 | Dodge,Grand 614 | Mazda,MX-5 615 | Dodge,Journey 616 | Mazda,CX-9 617 | Kia,Forte 618 | Honda,Civic 619 | Kia,Optima 620 | Kia,Rio 621 | Kia,Soul 622 | Volkswagen,Passat 623 | Volkswagen,Touareg 624 | GMC,Acadia 625 | GMC,Terrain 626 | GMC,Yukon 627 | Volvo,C70 628 | GMC,Savana 629 | Volkswagen,Golf 630 | Cadillac,CTS 631 | Jaguar,XF 632 | Jaguar,XJ 633 | Jaguar,XK 634 | Jeep,Liberty 635 | Cadillac,CTS-V 636 | Volkswagen,Routan 637 | Volkswagen,GTI 638 | Jeep,Patriot 639 | Volkswagen,Beetle 640 | Jeep,Wrangler 641 | Cadillac,SRX 642 | Cadillac,Escalade 643 | BMW,5 644 | Acura,RL 645 | Acura,TSX 646 | Acura,ZDX 647 | Acura,MDX 648 | Subaru,Legacy 649 | Mitsubishi,Galant 650 | Mitsubishi,Outlander 651 | Subaru,Outback 652 | Buick,Verano 653 | Suzuki,Kizashi 654 | Saab,09-Mar 655 | Subaru,Forester 656 | Suzuki,SX4 657 | Lincoln,MKZ 658 | Lincoln,MKS 659 | Lincoln,MKX 660 | Lincoln,MKT 661 | Bentley,Mulsanne 662 | Lincoln,Navigator 663 | Honda,CR-Z 664 | Honda,Fit 665 | Honda,Odyssey 666 | Honda,Pilot 667 | Lamborghini,Gallardo 668 | BMW,7 669 | --------------------------------------------------------------------------------