UI/Console/HDTSequenceEditor.xaml
|
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Task Sequence Editor" Height="760" Width="1180" MinHeight="480" MinWidth="820" WindowStartupLocation="Manual" Background="{DynamicResource HDTWindowBrush}"> <!-- THE TASK SEQUENCE EDITOR, opened from a task sequence in the browser. WHY IT IS ITS OWN WINDOW. Deployment Workbench lists task sequences in the tree and edits their steps in a properties dialog opened from one - step tree on the left, properties on the right, the actions across the top. CLAUDE.md asks for a console "deliberately close to Deployment Workbench so muscle memory transfers", and DESIGN 12 repeats it. IT IS ALSO THE ONLY WINDOW THAT WRITES. The browser opens a live share and promises to write nothing to it; an editing surface nested inside it would make that promise half-true, which is worse than either answer. WindowStartupLocation IS Manual, THE SAME AS THE BROWSER'S. Both windows open at the top-left of the work area, filling it, and Manual is the only value under which WPF honours the Left and Top the host assigns. CenterOwner would recentre this window over the browser after the assignment - and since the two are the same size, "centred over it" means a copy sitting a few pixels off the window it covers, which reads as a window that failed to line up rather than as a second one. IT IS STILL AN OWNED WINDOW. The owner is what keeps the editor above the browser it was opened from; only the POSITION stopped depending on it. THE ACTIONS ARE A TOOLBAR, NOT A ROW OF FILLED BUTTONS. MDT and ConfigMgr both draw them flat, and a row of solid blue pills is the one part of this window that would not read as Workbench to somebody arriving from it. HDTToolButton is that style; the Close button at the bottom keeps the console's filled one, because it is a dialog button and Workbench draws those filled too. ADD OPENS A MENU. Workbench hangs a drop-down off Add - General, Disks, Images - and an administrator picks 'Apply Operating System' rather than typing a type name. HDTAddMenu is where those items go; Get-HDTConsoleStepCatalog decides what they are, from the engine's own registry, so a step type dropped into Modules\ appears in the menu without this file being touched. THE RIGHT-HAND PANE IS TWO TABS, WHICH IS ALSO MDT'S SPLIT. Properties is what the step does; Options is whether it does it - the two checkboxes and the condition that filters it. The split is worth copying because the halves are read at different times: Properties when building a sequence, Options when working out why a deployment did something surprising. NO x:Class AND NO CODE-BEHIND, as HDTConsole.xaml and HDTWizard.xaml. Handlers are attached in PowerShell, by name, after the tree is loaded. NAMED CONTROLS ARE THE CONTRACT with New-HDTConsoleHost: HDTEditorTitleText, HDTEditorPathText, HDTStepTree, HDTStepDetail, HDTEditorCommandText, HDTAddButton, HDTAddMenu, HDTRemoveButton, HDTUpButton, HDTDownButton, HDTCopyButton, HDTPasteButton, HDTSaveButton, HDTOptionTab, HDTDisableCheck, HDTContinueCheck, HDTConditionText, HDTConditionApplyButton, HDTConditionClearButton, HDTConditionVariableBox, HDTConditionOperatorBox, HDTConditionValueBox, HDTConditionBuildButton, HDTRunInText and HDTEditorCloseButton. A test asserts every one of these names is here, so renaming one fails on a developer machine rather than in front of an administrator. THE DOCUMENT PATH IS IN THE BANNER, not just the id. Both of this lab's shares hold a DEMO-M4, so two editors opened at once would otherwise be identical windows over different files - and the difference only shows at the moment one of them saves. THE PALETTE IS THE CONSOLE'S. Every colour is a DynamicResource under the same keys HDTConsole.xaml declares, so Get-HDTConsoleTheme repaints both windows from one decision. --> <Window.Resources> <SolidColorBrush x:Key="HDTWindowBrush" Color="#FFF3F3F3" /> <SolidColorBrush x:Key="HDTBannerBrush" Color="#FF0E639C" /> <SolidColorBrush x:Key="HDTBannerTextBrush" Color="#FFFFFFFF" /> <SolidColorBrush x:Key="HDTBannerLabelBrush" Color="#FFD6E9F5" /> <SolidColorBrush x:Key="HDTPanelBrush" Color="#FFFFFFFF" /> <SolidColorBrush x:Key="HDTPanelTextBrush" Color="#FF1B1B1B" /> <SolidColorBrush x:Key="HDTBorderBrush" Color="#FFC8C8C8" /> <SolidColorBrush x:Key="HDTLabelBrush" Color="#FF0E639C" /> <SolidColorBrush x:Key="HDTCommandBrush" Color="#FFF7F7F7" /> <SolidColorBrush x:Key="HDTCommandTextBrush" Color="#FF0A3069" /> <SolidColorBrush x:Key="HDTFieldBrush" Color="#FFEDEDED" /> <SolidColorBrush x:Key="HDTFooterBrush" Color="#FFE8E8E8" /> <SolidColorBrush x:Key="HDTButtonBrush" Color="#FF0E639C" /> <SolidColorBrush x:Key="HDTButtonTextBrush" Color="#FFFFFFFF" /> <SolidColorBrush x:Key="HDTButtonHoverBrush" Color="#FFCCE4F7" /> <SolidColorBrush x:Key="HDTButtonHoverTextBrush" Color="#FF000000" /> <SolidColorBrush x:Key="HDTButtonPressedBrush" Color="#FFA9CFEC" /> <!-- The console's button, template and all. See HDTConsole.xaml for why the colours are Setters inside a ControlTemplate rather than local values on the element. --> <Style TargetType="Button"> <Setter Property="Background" Value="{DynamicResource HDTButtonBrush}" /> <Setter Property="Foreground" Value="{DynamicResource HDTButtonTextBrush}" /> <Setter Property="BorderThickness" Value="0" /> <Setter Property="FontSize" Value="13" /> <Setter Property="Padding" Value="14,6,14,6" /> <Setter Property="Margin" Value="0,0,8,0" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Button"> <Border x:Name="HDTButtonSurface" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Margin="{TemplateBinding Padding}" /> </Border> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter TargetName="HDTButtonSurface" Property="Background" Value="{DynamicResource HDTButtonHoverBrush}" /> <Setter Property="Foreground" Value="{DynamicResource HDTButtonHoverTextBrush}" /> </Trigger> <Trigger Property="IsPressed" Value="True"> <Setter TargetName="HDTButtonSurface" Property="Background" Value="{DynamicResource HDTButtonPressedBrush}" /> <Setter Property="Foreground" Value="{DynamicResource HDTButtonHoverTextBrush}" /> </Trigger> <!-- A disabled action must LOOK disabled. Remove, Up, Down, Copy and Save mean nothing until a row is selected, and a bright button that does nothing when pressed is how an administrator concludes the window is broken. --> <Trigger Property="IsEnabled" Value="False"> <Setter TargetName="HDTButtonSurface" Property="Background" Value="{DynamicResource HDTFooterBrush}" /> <Setter Property="Foreground" Value="{DynamicResource HDTBorderBrush}" /> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <!-- THE TOOLBAR BUTTON. Flat, transparent, text in the panel's own colour, lighting up only under the pointer - which is what every toolbar in Workbench, ConfigMgr and Explorer does, and what makes a row of eight actions read as a toolbar rather than as eight decisions of equal weight. --> <Style x:Key="HDTToolButton" TargetType="Button"> <Setter Property="Background" Value="Transparent" /> <Setter Property="Foreground" Value="{DynamicResource HDTPanelTextBrush}" /> <Setter Property="BorderThickness" Value="1" /> <Setter Property="BorderBrush" Value="Transparent" /> <Setter Property="FontSize" Value="13" /> <Setter Property="Padding" Value="11,5,11,5" /> <Setter Property="Margin" Value="0,0,2,0" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Button"> <Border x:Name="HDTToolSurface" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Margin="{TemplateBinding Padding}" /> </Border> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter TargetName="HDTToolSurface" Property="Background" Value="{DynamicResource HDTButtonHoverBrush}" /> <Setter TargetName="HDTToolSurface" Property="BorderBrush" Value="{DynamicResource HDTButtonPressedBrush}" /> <Setter Property="Foreground" Value="{DynamicResource HDTButtonHoverTextBrush}" /> </Trigger> <Trigger Property="IsPressed" Value="True"> <Setter TargetName="HDTToolSurface" Property="Background" Value="{DynamicResource HDTButtonPressedBrush}" /> <Setter Property="Foreground" Value="{DynamicResource HDTButtonHoverTextBrush}" /> </Trigger> <Trigger Property="IsEnabled" Value="False"> <Setter Property="Foreground" Value="{DynamicResource HDTBorderBrush}" /> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <!-- Checkboxes and labels take the panel's colour, so the Options tab survives the theme swap along with everything else. --> <Style TargetType="CheckBox"> <Setter Property="Foreground" Value="{DynamicResource HDTPanelTextBrush}" /> <Setter Property="FontFamily" Value="Segoe UI" /> <Setter Property="FontSize" Value="13" /> <Setter Property="Margin" Value="0,0,0,10" /> </Style> <Style TargetType="TabItem"> <Setter Property="Foreground" Value="{DynamicResource HDTPanelTextBrush}" /> <Setter Property="FontFamily" Value="Segoe UI" /> <Setter Property="FontSize" Value="12" /> <Setter Property="Padding" Value="14,5,14,5" /> </Style> </Window.Resources> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <!-- the banner: which task sequence, and which document --> <Border Grid.Row="0" Background="{DynamicResource HDTBannerBrush}" Padding="24,14,24,14"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <TextBlock Grid.Row="0" x:Name="HDTEditorTitleText" Foreground="{DynamicResource HDTBannerTextBrush}" FontFamily="Segoe UI" FontSize="17" FontWeight="SemiBold" /> <TextBlock Grid.Row="1" x:Name="HDTEditorPathText" Foreground="{DynamicResource HDTBannerLabelBrush}" FontFamily="Consolas, Courier New" FontSize="11" Margin="0,4,0,0" TextTrimming="CharacterEllipsis" /> </Grid> </Border> <!-- the actions, in Workbench's order and Workbench's weight --> <Border Grid.Row="1" Background="{DynamicResource HDTFooterBrush}" BorderBrush="{DynamicResource HDTBorderBrush}" BorderThickness="0,0,0,1" Padding="18,6,18,6"> <StackPanel Orientation="Horizontal"> <!-- The drop-down is the whole point of Add: an administrator picks a step type from a list the engine's registry produced, rather than typing one. --> <Button x:Name="HDTAddButton" Style="{StaticResource HDTToolButton}"> <Button.ContextMenu> <ContextMenu x:Name="HDTAddMenu" /> </Button.ContextMenu> </Button> <Button x:Name="HDTRemoveButton" Style="{StaticResource HDTToolButton}" IsEnabled="False" /> <Border Width="1" Margin="7,4,7,4" Background="{DynamicResource HDTBorderBrush}" /> <Button x:Name="HDTUpButton" Style="{StaticResource HDTToolButton}" IsEnabled="False" /> <Button x:Name="HDTDownButton" Style="{StaticResource HDTToolButton}" IsEnabled="False" /> <Border Width="1" Margin="7,4,7,4" Background="{DynamicResource HDTBorderBrush}" /> <Button x:Name="HDTCopyButton" Style="{StaticResource HDTToolButton}" IsEnabled="False" /> <Button x:Name="HDTPasteButton" Style="{StaticResource HDTToolButton}" IsEnabled="False" /> <Border Width="1" Margin="7,4,7,4" Background="{DynamicResource HDTBorderBrush}" /> <Button x:Name="HDTSaveButton" Style="{StaticResource HDTToolButton}" IsEnabled="False" /> <Border Width="1" Margin="7,4,7,4" Background="{DynamicResource HDTBorderBrush}" /> <!-- THE TABS BELONG TO THE SELECTED STEP; THIS BELONGS TO THE SEQUENCE. Properties, Disk and Options all change as the tree selection moves, so the variables block - which is the document's, not any step's - was in the wrong strip and nobody found it. Sequence-level actions live on the toolbar, beside Save. --> <Button x:Name="HDTVariableButton" Style="{StaticResource HDTToolButton}" /> </StackPanel> </Border> <!-- steps on the left, the two tabs on the right --> <Grid Grid.Row="2" Margin="24,16,24,0"> <Grid.ColumnDefinitions> <ColumnDefinition Width="360" MinWidth="220" /> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="*" MinWidth="280" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <TextBlock Grid.Row="0" Grid.Column="0" x:Name="HDTEditorStepsLabel" Foreground="{DynamicResource HDTLabelBrush}" FontSize="12" Margin="0,0,0,6" /> <TreeView Grid.Row="1" Grid.Column="0" x:Name="HDTStepTree" Background="{DynamicResource HDTPanelBrush}" Foreground="{DynamicResource HDTPanelTextBrush}" BorderBrush="{DynamicResource HDTBorderBrush}" BorderThickness="1" FontFamily="Segoe UI" FontSize="13" ScrollViewer.HorizontalScrollBarVisibility="Disabled"> <TreeView.ItemContainerStyle> <Style TargetType="TreeViewItem"> <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" /> <!-- A splice rebuilds the tree, so the row that was selected no longer exists as an object. The rows carry their own selection and this binding puts it back - without it the highlight falls to the nearest container, which is why switching a step off used to leave its GROUP selected. --> <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" /> <Setter Property="Foreground" Value="{DynamicResource HDTPanelTextBrush}" /> <Setter Property="Padding" Value="2,3,2,3" /> <!-- Without this a row announces itself as a dump of the whole object to a screen reader. See HDTConsole.xaml. --> <Setter Property="AutomationProperties.Name" Value="{Binding Text}" /> <!-- A STEP IS A LEAF AND MUST NOT LOOK LIKE A BRANCH. The stock TreeViewItem template draws its expander for every row and merely hides the glyph on a childless one, which still leaves a clickable triangle-shaped gap - and in a window whose whole subject is "which of these contains which", a step that appears to open is a step an administrator clicks at and gets nothing from. The template below is the stock one with the ToggleButton bound to HasItems, so a group gets a triangle and a step gets flat indentation. Groups keep the same indent as before, because the column the toggle occupied is still reserved by the 19-unit ColumnDefinition. --> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="TreeViewItem"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="19" /> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition /> </Grid.RowDefinitions> <ToggleButton x:Name="HDTExpander" Grid.Row="0" Grid.Column="0" ClickMode="Press" Focusable="False" IsChecked="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}"> <ToggleButton.Template> <ControlTemplate TargetType="ToggleButton"> <Border Background="Transparent" Padding="5,4,5,4"> <Path x:Name="HDTArrow" Data="M 0 0 L 4 4 L 0 8 Z" Fill="{DynamicResource HDTPanelTextBrush}" /> </Border> <ControlTemplate.Triggers> <Trigger Property="IsChecked" Value="True"> <Setter TargetName="HDTArrow" Property="Data" Value="M 0 4 L 8 4 L 4 8 Z" /> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </ToggleButton.Template> </ToggleButton> <Border x:Name="HDTRowSurface" Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}"> <ContentPresenter x:Name="PART_Header" ContentSource="Header" HorizontalAlignment="Left" /> </Border> <ItemsPresenter x:Name="HDTItems" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" /> </Grid> <ControlTemplate.Triggers> <!-- A leaf has no toggle at all. --> <Trigger Property="HasItems" Value="False"> <Setter TargetName="HDTExpander" Property="Visibility" Value="Collapsed" /> </Trigger> <Trigger Property="IsExpanded" Value="False"> <Setter TargetName="HDTItems" Property="Visibility" Value="Collapsed" /> </Trigger> <Trigger Property="IsSelected" Value="True"> <Setter TargetName="HDTRowSurface" Property="Background" Value="{DynamicResource HDTButtonHoverBrush}" /> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> </TreeView.ItemContainerStyle> <TreeView.ItemTemplate> <HierarchicalDataTemplate ItemsSource="{Binding Children}"> <StackPanel Orientation="Horizontal"> <!-- COLOURED, AND THE COLOUR IS THE ROW'S. Bound rather than themed: see Get-HDTConsoleIconColor for why a per-row DynamicResource key is not possible in markup XamlReader loads. WPF converts the string to a Brush through the target property's own type converter. --> <TextBlock Text="{Binding Icon}" Foreground="{Binding IconColor}" FontFamily="Segoe UI Emoji, Segoe UI Symbol" FontSize="13" Margin="0,0,7,0" VerticalAlignment="Center" /> <TextBlock Text="{Binding Text}" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" /> </StackPanel> </HierarchicalDataTemplate> </TreeView.ItemTemplate> </TreeView> <GridSplitter Grid.Row="0" Grid.RowSpan="2" Grid.Column="1" x:Name="HDTEditorSplitter" Width="8" Margin="6,0,6,0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="{DynamicResource HDTBorderBrush}" ShowsPreview="False" /> <Grid Grid.Row="0" Grid.RowSpan="2" Grid.Column="2"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <!-- THE STEP'S NAME, ABOVE THE TABS - which is where MDT puts it, and it has to be somewhere that is not a tab: a step with a page of its own has no Properties tab, and renaming it cannot depend on a tab that is not there. IT WRITES ON LOSING FOCUS, like every other box that writes a key here. The name is what every editing command refers to the step by, so a rename is a splice like any other. --> <Grid Grid.Row="0" Margin="0,0,0,8"> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <!-- THE SAME COLOUR AS EVERY OTHER FIELD LABEL. The blue is this console's heading colour - 'Steps', 'Conditions' - and using it here made the one label above the tabs read as a section title beside rows that are its peers. --> <TextBlock Grid.Column="0" x:Name="HDTStepNameLabel" Foreground="{DynamicResource HDTPanelTextBrush}" FontSize="12" VerticalAlignment="Center" Margin="0,0,10,0" /> <!-- WHITE, WHICH IS WHAT AN EDITABLE BOX IS IN THIS WINDOW. HDTFieldBrush is the READ-ONLY wash - the Properties rows switch to it through a DataTrigger - so painting an editable box with it says "you cannot type here". --> <TextBox Grid.Column="1" x:Name="HDTStepNameBox" Background="{DynamicResource HDTPanelBrush}" Foreground="{DynamicResource HDTPanelTextBrush}" BorderBrush="{DynamicResource HDTBorderBrush}" BorderThickness="1" FontFamily="Segoe UI" FontSize="12" Padding="6,5,6,5" /> </Grid> <TabControl Grid.Row="1" x:Name="HDTOptionTab" Background="{DynamicResource HDTPanelBrush}" BorderBrush="{DynamicResource HDTBorderBrush}" BorderThickness="1"> <!-- WHAT THE STEP DOES, AND THE ROWS THAT WRITE IT. A ROW DECIDES ITS OWN BOX. IsReadOnly is bound to the row's Editable, which Get-HDTConsoleStepNode set by naming the YAML key the row writes - so the window holds no list of which labels are typeable and cannot disagree with the splice about it. 'Type' and 'Runs' come through read-only: one is refused by Set-HDTStepProperty and the other is a position rather than anything in the file. A READ-ONLY BOX ALSO LOOKS READ-ONLY. A grey field that silently ignores typing is the same insult as a bright button that does nothing. Text IS TwoWay AND COMMITS ON EVERY KEYSTROKE, deliberately: the row object IS the edit buffer, Apply diffs it against Original, and LostFocus - the default for TextBox - would lose whatever was typed into the last box before the button was pressed, because pressing it is what moves the focus. --> <TabItem x:Name="HDTPropertyTab"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <ScrollViewer Grid.Row="0" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" Padding="14,12,14,12"> <ItemsControl x:Name="HDTStepDetail"> <ItemsControl.ItemTemplate> <DataTemplate> <Grid Margin="0,0,0,8"> <Grid.ColumnDefinitions> <ColumnDefinition Width="150" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <TextBlock Grid.Column="0" Text="{Binding Label}" Foreground="{DynamicResource HDTPanelTextBrush}" FontFamily="Segoe UI" FontSize="12" TextWrapping="Wrap" Margin="0,5,10,0" VerticalAlignment="Top" /> <TextBox x:Name="HDTFieldBox" Grid.Column="1" Text="{Binding Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsReadOnly="{Binding ReadOnly}" AcceptsReturn="True" TextWrapping="Wrap" Background="{DynamicResource HDTPanelBrush}" Foreground="{DynamicResource HDTPanelTextBrush}" BorderBrush="{DynamicResource HDTBorderBrush}" BorderThickness="1" FontFamily="Consolas, Courier New" FontSize="12" Padding="6,4,6,4" /> </Grid> <DataTemplate.Triggers> <DataTrigger Binding="{Binding ReadOnly}" Value="True"> <Setter TargetName="HDTFieldBox" Property="Background" Value="{DynamicResource HDTFieldBrush}" /> </DataTrigger> </DataTemplate.Triggers> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> </ScrollViewer> <!-- NO Apply AND NO Revert HERE ANY MORE. The rows are an edit buffer, so something has to decide when typing becomes a splice - but the toolbar Save is what an administrator expects to commit a window, and a second commit button on one tab of five taught that the other four did not need one. The boxes are banked before Save writes and before the pane is refilled for another step, which is every moment they could be lost. --> </Grid> </TabItem> <!-- THE OPERATING SYSTEM. MDT's Install Operating System page, where an image is PICKED out of the share rather than typed and found to be misspelled at the machine. THE LIST IS THE SHARE'S. Get-HDTConsoleImageChoice reads the same catalog the browser does, so this window cannot offer one the engine will not resolve - and an image the document names but the share no longer holds still appears, marked, rather than being silently swapped for whatever sorts first. THE EXPLANATIONS ARE BEHIND A ? AT THE END OF EACH ROW, as they are on the validation page: they are read once, when a setting is new, and a paragraph under every row turns four settings into a page that has to be scrolled. --> <TabItem x:Name="HDTImageTab"> <Grid Margin="14,12,14,12"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="150" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="30" /> </Grid.ColumnDefinitions> <Grid.Resources> <!-- THE ? THE VALIDATION PAGE USES, and for the same reason it is a Border rather than a bare glyph: WPF raises a tooltip only over what is painted, so a question mark with no surface has to be hit within a pixel or two - which reads as a tooltip that does not work. --> <Style TargetType="Border" x:Key="HDTHelpDot"> <Setter Property="Background" Value="Transparent" /> <Setter Property="Width" Value="22" /> <Setter Property="Height" Value="22" /> <Setter Property="CornerRadius" Value="11" /> <Setter Property="BorderBrush" Value="{DynamicResource HDTBorderBrush}" /> <Setter Property="BorderThickness" Value="1" /> <Setter Property="HorizontalAlignment" Value="Right" /> <Setter Property="VerticalAlignment" Value="Center" /> <Setter Property="Cursor" Value="Help" /> <Setter Property="Margin" Value="0,0,0,8" /> <Setter Property="ToolTipService.ShowDuration" Value="60000" /> <Setter Property="ToolTipService.InitialShowDelay" Value="200" /> </Style> <Style TargetType="TextBlock" x:Key="HDTHelpGlyph"> <Setter Property="Text" Value="?" /> <Setter Property="Foreground" Value="{DynamicResource HDTLabelBrush}" /> <Setter Property="FontFamily" Value="Segoe UI" /> <Setter Property="FontSize" Value="12" /> <Setter Property="FontWeight" Value="Bold" /> <Setter Property="HorizontalAlignment" Value="Center" /> <Setter Property="VerticalAlignment" Value="Center" /> </Style> <Style TargetType="TextBlock" x:Key="HDTFieldLabel"> <Setter Property="Foreground" Value="{DynamicResource HDTPanelTextBrush}" /> <Setter Property="FontSize" Value="12" /> <Setter Property="VerticalAlignment" Value="Center" /> <Setter Property="Margin" Value="0,0,10,8" /> </Style> </Grid.Resources> <TextBlock Grid.Row="0" Grid.Column="0" x:Name="HDTImageOsLabel" Style="{StaticResource HDTFieldLabel}" /> <ComboBox Grid.Row="0" Grid.Column="1" x:Name="HDTImageBox" DisplayMemberPath="Display" SelectedValuePath="Id" Margin="0,0,0,8" /> <Border Grid.Row="0" Grid.Column="2" Style="{StaticResource HDTHelpDot}"> <Border.ToolTip> <ToolTip MaxWidth="380"> <TextBlock TextWrapping="Wrap" x:Name="HDTImageOsHint" /> </ToolTip> </Border.ToolTip> <TextBlock Style="{StaticResource HDTHelpGlyph}" /> </Border> <TextBlock Grid.Row="1" Grid.Column="0" x:Name="HDTImageIndexLabel" Style="{StaticResource HDTFieldLabel}" /> <!-- THE EDITIONS os.yaml CARRIES, not a number to type and hope. Editable because a sequence may name the index through a variable. --> <ComboBox Grid.Row="1" Grid.Column="1" x:Name="HDTImageIndexBox" DisplayMemberPath="Display" SelectedValuePath="Index" IsEditable="True" Margin="0,0,0,8" /> <Border Grid.Row="1" Grid.Column="2" Style="{StaticResource HDTHelpDot}"> <Border.ToolTip> <ToolTip MaxWidth="380"> <TextBlock TextWrapping="Wrap" x:Name="HDTImageIndexHint" /> </ToolTip> </Border.ToolTip> <TextBlock Style="{StaticResource HDTHelpGlyph}" /> </Border> <TextBlock Grid.Row="2" Grid.Column="0" x:Name="HDTImageDestinationLabel" Style="{StaticResource HDTFieldLabel}" /> <ComboBox Grid.Row="2" Grid.Column="1" x:Name="HDTImageTargetBox" IsEditable="True" Margin="0,0,0,8" /> <Border Grid.Row="2" Grid.Column="2" Style="{StaticResource HDTHelpDot}"> <Border.ToolTip> <ToolTip MaxWidth="380"> <TextBlock TextWrapping="Wrap" x:Name="HDTImageDestinationHint" /> </ToolTip> </Border.ToolTip> <TextBlock Style="{StaticResource HDTHelpGlyph}" /> </Border> <TextBlock Grid.Row="3" Grid.Column="0" x:Name="HDTImageTimeoutLabel" Style="{StaticResource HDTFieldLabel}" /> <Grid Grid.Row="3" Grid.Column="1"> <Grid.ColumnDefinitions> <ColumnDefinition Width="90" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <TextBox Grid.Column="0" x:Name="HDTImageTimeoutBox" Background="{DynamicResource HDTPanelBrush}" Foreground="{DynamicResource HDTPanelTextBrush}" BorderBrush="{DynamicResource HDTBorderBrush}" BorderThickness="1" FontFamily="Consolas, Courier New" FontSize="12" Padding="6,5,6,5" /> <TextBlock Grid.Column="1" x:Name="HDTImageTimeoutUnitText" Foreground="{DynamicResource HDTPanelTextBrush}" FontSize="12" VerticalAlignment="Center" Margin="8,0,0,0" /> </Grid> <Border Grid.Row="3" Grid.Column="2" Style="{StaticResource HDTHelpDot}"> <Border.ToolTip> <ToolTip MaxWidth="380"> <TextBlock TextWrapping="Wrap" x:Name="HDTImageTimeoutHint" /> </ToolTip> </Border.ToolTip> <TextBlock Style="{StaticResource HDTHelpGlyph}" /> </Border> <Border Grid.Row="5" Grid.ColumnSpan="3" Padding="0,10,0,0" BorderBrush="{DynamicResource HDTBorderBrush}" BorderThickness="0,1,0,0"> <StackPanel Orientation="Horizontal"> <Button x:Name="HDTImageApplyButton" Style="{StaticResource HDTToolButton}" /> <Button x:Name="HDTImageRevertButton" Style="{StaticResource HDTToolButton}" /> </StackPanel> </Border> </Grid> </TabItem> <!-- THE VALIDATION. MDT's Validate dialog is a column of checkboxes, each with the value it checks against, and this is that page. NOTHING HERE NAMES A CHECK. The rows are bound from Get-HDTConsoleValidateCheck, which reads one table in the engine - so a check added tomorrow appears on this page without this file being touched. That is the difference between a list of settings and six hand-written rows that have to be kept in step with the step that reads them. UNTICKED MEANS THE KEY IS REMOVED, not set to zero: a bound of nothing still reads as a declared bound. --> <TabItem x:Name="HDTValidateTab"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <ScrollViewer Grid.Row="0" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" Padding="14,12,14,12"> <ItemsControl x:Name="HDTValidateList"> <ItemsControl.ItemTemplate> <DataTemplate> <Grid Margin="0,0,0,10"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="110" /> <ColumnDefinition Width="34" /> <ColumnDefinition Width="26" /> </Grid.ColumnDefinitions> <CheckBox Grid.Column="0" Content="{Binding Label}" IsChecked="{Binding Enabled, Mode=TwoWay}" Foreground="{DynamicResource HDTPanelTextBrush}" VerticalAlignment="Center" /> <!-- THE VALUE FOLLOWS THE TICK. An unticked check is not being made, so its value is not being read - and a live box beside a dark checkbox invites a number that changes nothing. --> <TextBox Grid.Column="1" Text="{Binding Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsEnabled="{Binding Enabled}" Visibility="{Binding ValueVisibility}" Background="{DynamicResource HDTPanelBrush}" Foreground="{DynamicResource HDTPanelTextBrush}" BorderBrush="{DynamicResource HDTBorderBrush}" BorderThickness="1" FontFamily="Consolas, Courier New" FontSize="12" Padding="6,4,6,4" VerticalContentAlignment="Center" /> <TextBlock Grid.Column="2" Text="{Binding Unit}" Foreground="{DynamicResource HDTPanelTextBrush}" FontSize="12" VerticalAlignment="Center" Margin="8,0,0,0" /> <!-- THE HINT IS BEHIND A ? RATHER THAN UNDER THE ROW. Six paragraphs of explanation turn a short list into a page that has to be scrolled to be counted - and the explanations are read once, when a check is new, not every time the page is opened. A ToolTip AND NOT A POPUP: it needs no handler, so the untested adapter gains nothing to get wrong. --> <!-- A BARE GLYPH IS A HIT TARGET THE SIZE OF THE INK. WPF only raises the tooltip over what is actually painted, so a question mark with no surface has to be hit within a couple of pixels - which reads as a tooltip that does not work. The Border is transparent and hit-testable, so the whole square answers. ShowDuration IS RAISED because these hints are two sentences and the default five seconds is not enough to read them. --> <Border Grid.Column="3" Background="Transparent" Width="22" Height="22" CornerRadius="11" BorderBrush="{DynamicResource HDTBorderBrush}" BorderThickness="1" HorizontalAlignment="Right" VerticalAlignment="Center" Cursor="Help" ToolTipService.ShowDuration="60000" ToolTipService.InitialShowDelay="200"> <Border.ToolTip> <ToolTip MaxWidth="380"> <TextBlock Text="{Binding Hint}" TextWrapping="Wrap" /> </ToolTip> </Border.ToolTip> <TextBlock Text="?" Foreground="{DynamicResource HDTLabelBrush}" FontFamily="Segoe UI" FontSize="12" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center" /> </Border> </Grid> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> </ScrollViewer> <Border Grid.Row="1" Padding="14,10,14,12" BorderBrush="{DynamicResource HDTBorderBrush}" BorderThickness="0,1,0,0"> <StackPanel Orientation="Horizontal"> <!-- ONE PRESS WRITES THE WHOLE PAGE, which is MDT's OK. Writing on every keystroke would splice the document six times while somebody types a number. --> <Button x:Name="HDTValidateApplyButton" Style="{StaticResource HDTToolButton}" /> <Button x:Name="HDTValidateRevertButton" Style="{StaticResource HDTToolButton}" /> </StackPanel> </Border> </Grid> </TabItem> <!-- THE DISK. MDT's Format and Partition Disk page, and laid out the way that page is: which disk and how it is partitioned at the top, the volume list below it, and the list's own buttons above its right-hand corner. IT IS HIDDEN FOR EVERY OTHER STEP TYPE, by the host, and hidden rather than empty: a Disk tab over Apply OS is a tab that has nothing to say and invites a click that finds out. EVERY BUTTON HERE IS A COMMAND. New and Edit open the Partition Properties dialog and end in Add-HDTStepPartition or Set-HDTStepPartition; the delete glyph is Remove-HDTStepPartition and the arrows are Move-HDTStepPartition. The strip at the bottom of the window shows the one that just ran. --> <TabItem x:Name="HDTDiskTab"> <Grid Margin="14,12,14,12"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <!-- WHICH DISK, AND LAID OUT HOW. Both belong to the same decision, so they sit together at the top of the page as they do in MDT - rather than one here and one over on Properties. --> <Grid Grid.Row="0" Margin="0,0,0,10"> <Grid.ColumnDefinitions> <ColumnDefinition Width="110" /> <ColumnDefinition Width="70" /> <ColumnDefinition Width="24" /> <ColumnDefinition Width="90" /> <ColumnDefinition Width="190" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <TextBlock Grid.Column="0" x:Name="HDTDiskNumberLabel" Foreground="{DynamicResource HDTPanelTextBrush}" VerticalAlignment="Center" /> <TextBox Grid.Column="1" x:Name="HDTDiskNumberBox" /> <TextBlock Grid.Column="3" x:Name="HDTDiskStyleLabel" Foreground="{DynamicResource HDTPanelTextBrush}" VerticalAlignment="Center" /> <ComboBox Grid.Column="4" x:Name="HDTDiskStyleBox" /> </Grid> <CheckBox Grid.Row="1" x:Name="HDTDiskWipeCheck" Foreground="{DynamicResource HDTPanelTextBrush}" Margin="0,0,0,12" /> <!-- THE LIST'S OWN BUTTONS, ABOVE THE LIST, as they are in Workbench. Glyphs rather than words because the row of them is what says "these act on the list" - and Segoe UI Symbol because WinPE has no icon pipeline and the console should not need one. --> <Grid Grid.Row="2" Margin="0,0,0,4"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <TextBlock Grid.Column="0" x:Name="HDTPartitionListLabel" Foreground="{DynamicResource HDTPanelTextBrush}" VerticalAlignment="Center" /> <StackPanel Grid.Column="1" Orientation="Horizontal"> <Button x:Name="HDTPartitionAddButton" Content="" FontFamily="Segoe UI Symbol" FontSize="13" MinWidth="34" Margin="0,0,4,0" /> <Button x:Name="HDTPartitionEditButton" Content="" FontFamily="Segoe UI Symbol" FontSize="13" MinWidth="34" Margin="0,0,4,0" /> <Button x:Name="HDTPartitionRemoveButton" Content="" FontFamily="Segoe UI Symbol" FontSize="13" MinWidth="34" Margin="0,0,12,0" /> <Button x:Name="HDTPartitionUpButton" Content="" FontFamily="Segoe UI Symbol" FontSize="13" MinWidth="34" Margin="0,0,4,0" /> <Button x:Name="HDTPartitionDownButton" Content="" FontFamily="Segoe UI Symbol" FontSize="13" MinWidth="34" Margin="0" /> </StackPanel> </Grid> <!-- THE HEADER IS A ROW OF ITS OWN, not a GridView: the rest of this console is ItemsControl and DataTemplate against the theme's brushes, and one ListView here would arrive with a whole second set of default colours to override. The widths are repeated in the row template below. They have to match, and a shared-size group would be three more lines to say what two matching sets of numbers already say. --> <Grid Grid.Row="3" Margin="0,0,0,4"> <Grid.ColumnDefinitions> <ColumnDefinition Width="24" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="80" /> <ColumnDefinition Width="100" /> <ColumnDefinition Width="70" /> <ColumnDefinition Width="50" /> <ColumnDefinition Width="46" /> <ColumnDefinition Width="120" /> </Grid.ColumnDefinitions> <TextBlock Grid.Column="0" Text="#" /> <TextBlock Grid.Column="1" x:Name="HDTPartitionNameHeader" /> <TextBlock Grid.Column="2" x:Name="HDTPartitionTypeHeader" /> <TextBlock Grid.Column="3" x:Name="HDTPartitionSizeHeader" /> <TextBlock Grid.Column="4" x:Name="HDTPartitionFormatHeader" /> <TextBlock Grid.Column="5" x:Name="HDTPartitionQuickHeader" /> <TextBlock Grid.Column="6" x:Name="HDTPartitionBootHeader" /> <TextBlock Grid.Column="7" x:Name="HDTPartitionVariableHeader" /> <Grid.Resources> <Style TargetType="TextBlock"> <Setter Property="Foreground" Value="{DynamicResource HDTHintTextBrush}" /> <Setter Property="FontFamily" Value="Segoe UI" /> <Setter Property="FontSize" Value="11" /> <Setter Property="Margin" Value="0,0,8,0" /> </Style> </Grid.Resources> </Grid> <Border Grid.Row="4" MinHeight="120" Background="{DynamicResource HDTFieldBrush}" BorderBrush="{DynamicResource HDTBorderBrush}" BorderThickness="1"> <ListBox x:Name="HDTPartitionList" BorderThickness="0" Background="Transparent" HorizontalContentAlignment="Stretch" ScrollViewer.HorizontalScrollBarVisibility="Disabled"> <ListBox.ItemTemplate> <DataTemplate> <Grid Margin="0,1,0,1"> <Grid.ColumnDefinitions> <ColumnDefinition Width="24" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="80" /> <ColumnDefinition Width="100" /> <ColumnDefinition Width="70" /> <ColumnDefinition Width="50" /> <ColumnDefinition Width="46" /> <ColumnDefinition Width="120" /> </Grid.ColumnDefinitions> <TextBlock Grid.Column="0" Text="{Binding Order}" /> <TextBlock Grid.Column="1" Text="{Binding Name}" /> <TextBlock Grid.Column="2" Text="{Binding Type}" /> <!-- AS AUTHORED. 60% and remainder are not byte counts and what they come to depends on the machine, so the grid prints the words the document uses. --> <TextBlock Grid.Column="3" Text="{Binding Size}" /> <TextBlock Grid.Column="4" Text="{Binding FileSystem}" /> <TextBlock Grid.Column="5" Text="{Binding QuickText}" /> <TextBlock Grid.Column="6" Text="{Binding BootText}" /> <TextBlock Grid.Column="7" Text="{Binding Variable}" /> <Grid.Resources> <Style TargetType="TextBlock"> <Setter Property="FontFamily" Value="Consolas, Courier New" /> <Setter Property="FontSize" Value="12" /> <Setter Property="TextTrimming" Value="CharacterEllipsis" /> <Setter Property="Margin" Value="0,0,8,0" /> </Style> </Grid.Resources> </Grid> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </Border> <TextBlock Grid.Row="5" x:Name="HDTPartitionStyleText" Foreground="{DynamicResource HDTHintTextBrush}" FontFamily="Segoe UI" FontSize="11" TextWrapping="Wrap" Margin="0,10,0,0" /> </Grid> </TabItem> <!-- WHETHER IT DOES IT. Workbench's Options tab: the two checkboxes, then the filter. --> <!-- THE BLOCK THE NEW SEQUENCE WINDOW FILLS. Its wizard asks for the administrator password, the OS image and the organisation, writes them into variables:, and until this tab existed nothing could change them again - an administrator who mistyped the password re-created the sequence. NOTHING IS MASKED, INCLUDING THE PASSWORD. It is stored readable in the document because WinPE uses it with nobody present; a masked box over a readable file is theatre, and it stops somebody checking what they typed. --> <!-- Header collapsed: the toolbar button selects it. A tab about the sequence sitting among tabs about the selected step is what hid it in the first place. --> <TabItem x:Name="HDTVariableTab" Visibility="Collapsed"> <Grid Margin="16,14,16,14"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <TextBlock x:Name="HDTVariableHint" Grid.Row="0" Foreground="{DynamicResource HDTHintTextBrush}" FontFamily="Segoe UI" FontSize="12" TextWrapping="Wrap" Margin="0,0,0,10" /> <Border Grid.Row="1" Background="{DynamicResource HDTPanelBrush}" BorderBrush="{DynamicResource HDTBorderBrush}" BorderThickness="1"> <DataGrid x:Name="HDTVariableGrid" AutoGenerateColumns="False" HeadersVisibility="Column" CanUserAddRows="False" CanUserDeleteRows="False" CanUserResizeRows="False" GridLinesVisibility="Horizontal" BorderThickness="0" Background="Transparent" RowBackground="Transparent" FontFamily="Segoe UI" FontSize="13"> <DataGrid.Columns> <DataGridTextColumn x:Name="HDTVariableNameColumn" Binding="{Binding Name}" Width="220" IsReadOnly="True" /> <DataGridTextColumn x:Name="HDTVariableValueColumn" Binding="{Binding Value}" Width="240" /> <DataGridTextColumn x:Name="HDTVariableHintColumn" Binding="{Binding Hint}" Width="*" IsReadOnly="True" /> </DataGrid.Columns> </DataGrid> </Border> <StackPanel Grid.Row="2" Orientation="Horizontal" Margin="0,12,0,0"> <TextBlock x:Name="HDTVariableNameLabel" VerticalAlignment="Center" Foreground="{DynamicResource HDTLabelBrush}" FontFamily="Segoe UI" FontSize="12" Margin="0,0,8,0" /> <!-- EDITABLE, NOT A FIXED LIST. Every variable HDT publishes is offered, and typing filters them - but a sequence may carry a name of its own for a custom step to read, so the box still takes anything. IsEditable with StaysOpenOnEdit is what keeps the list up while somebody types into it. --> <ComboBox x:Name="HDTVariableNameBox" Width="230" Margin="0,0,10,0" IsEditable="True" StaysOpenOnEdit="True" IsTextSearchEnabled="False" MaxDropDownHeight="220" /> <TextBlock x:Name="HDTVariableValueLabel" VerticalAlignment="Center" Foreground="{DynamicResource HDTLabelBrush}" FontFamily="Segoe UI" FontSize="12" Margin="0,0,8,0" /> <TextBox x:Name="HDTVariableValueBox" Width="220" Margin="0,0,10,0" /> <Button x:Name="HDTVariableSetButton" MinWidth="80" Margin="0,0,10,0" /> <Button x:Name="HDTVariableRemoveButton" MinWidth="90" Margin="0" /> </StackPanel> </Grid> </TabItem> <TabItem x:Name="HDTOptionsTab"> <ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" Padding="16,14,16,14"> <StackPanel> <CheckBox x:Name="HDTDisableCheck" /> <CheckBox x:Name="HDTContinueCheck" /> <Border Height="1" Margin="0,6,0,14" Background="{DynamicResource HDTBorderBrush}" /> <TextBlock x:Name="HDTConditionLabel" Foreground="{DynamicResource HDTLabelBrush}" FontFamily="Segoe UI" FontSize="12" Margin="0,0,0,4" /> <TextBlock x:Name="HDTConditionHint" Foreground="{DynamicResource HDTPanelTextBrush}" FontFamily="Segoe UI" FontSize="12" TextWrapping="Wrap" Margin="0,0,0,8" /> <!-- THE PICKER, ABOVE THE BOX RATHER THAN INSTEAD OF IT. The grammar is closed - a %Var% token, one of four operators, a value - so the legal conditions are enumerable and a blank box is the worst way to enter one: it accepts '%HDTIsUEFI% = true', which is not the grammar, and the document is then refused at import, on the share, by somebody who did not type it. THE BOX STAYS because an author may want something the three lists cannot say, and because it is what SHOWS the condition a step already has. Build writes into it; it is not a second way to save. WHAT IS IN THE LISTS IS Get-HDTConsoleConditionOption'S - every variable the engine knows, the four operators it implements, and the values worth offering for the facts that have a closed set. --> <Grid Margin="0,0,0,8"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <ComboBox Grid.Column="0" x:Name="HDTConditionVariableBox" DisplayMemberPath="Name" SelectedValuePath="Token" FontFamily="Segoe UI" FontSize="12" Margin="0,0,6,0" /> <ComboBox Grid.Column="1" x:Name="HDTConditionOperatorBox" DisplayMemberPath="Display" SelectedValuePath="Token" MinWidth="150" FontFamily="Segoe UI" FontSize="12" Margin="0,0,6,0" /> <!-- EDITABLE, because most variables have no closed set - a computer name has no menu - and IsEditable is what lets one control be both a menu and a box. --> <ComboBox Grid.Column="2" x:Name="HDTConditionValueBox" IsEditable="True" MinWidth="130" FontFamily="Consolas, Courier New" FontSize="12" Margin="0,0,6,0" /> <Button Grid.Column="3" x:Name="HDTConditionBuildButton" Style="{StaticResource HDTToolButton}" /> </Grid> <TextBox x:Name="HDTConditionText" MinHeight="64" AcceptsReturn="True" TextWrapping="Wrap" VerticalScrollBarVisibility="Auto" Background="{DynamicResource HDTFieldBrush}" Foreground="{DynamicResource HDTPanelTextBrush}" BorderBrush="{DynamicResource HDTBorderBrush}" BorderThickness="1" FontFamily="Consolas, Courier New" FontSize="12" Padding="7,5,7,5" /> <StackPanel Orientation="Horizontal" Margin="0,10,0,0"> <Button x:Name="HDTConditionApplyButton" Style="{StaticResource HDTToolButton}" IsEnabled="False" /> <Button x:Name="HDTConditionClearButton" Style="{StaticResource HDTToolButton}" IsEnabled="False" /> </StackPanel> <Border Height="1" Margin="0,16,0,14" Background="{DynamicResource HDTBorderBrush}" /> <!-- The phase is a filter too, and running in the wrong one is the commonest reason a step is silently skipped. --> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="150" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <TextBlock Grid.Column="0" x:Name="HDTRunInLabel" Foreground="{DynamicResource HDTPanelTextBrush}" FontFamily="Segoe UI" FontSize="12" /> <TextBlock Grid.Column="1" x:Name="HDTRunInText" Foreground="{DynamicResource HDTPanelTextBrush}" FontFamily="Consolas, Courier New" FontSize="12" /> </Grid> </StackPanel> </ScrollViewer> </TabItem> </TabControl> </Grid> </Grid> <!-- the cmdlet for the selected row, and the way out --> <Grid Grid.Row="3" Margin="24,16,24,20"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <Border Grid.Row="0" Background="{DynamicResource HDTCommandBrush}" BorderBrush="{DynamicResource HDTBorderBrush}" BorderThickness="1" Padding="10,7,10,7"> <TextBox x:Name="HDTEditorCommandText" Text="" IsReadOnly="True" BorderThickness="0" Background="Transparent" Foreground="{DynamicResource HDTCommandTextBrush}" FontFamily="Consolas, Courier New" FontSize="12" TextWrapping="Wrap" /> </Border> <StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,14,0,0"> <Button x:Name="HDTEditorCloseButton" MinWidth="96" Margin="0" /> </StackPanel> </Grid> </Grid> </Window> |