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="&#xE109;"
                                        FontFamily="Segoe UI Symbol" FontSize="13"
                                        MinWidth="34" Margin="0,0,4,0" />
                                <Button x:Name="HDTPartitionEditButton" Content="&#xE104;"
                                        FontFamily="Segoe UI Symbol" FontSize="13"
                                        MinWidth="34" Margin="0,0,4,0" />
                                <Button x:Name="HDTPartitionRemoveButton" Content="&#xE10A;"
                                        FontFamily="Segoe UI Symbol" FontSize="13"
                                        MinWidth="34" Margin="0,0,12,0" />
                                <Button x:Name="HDTPartitionUpButton" Content="&#xE010;"
                                        FontFamily="Segoe UI Symbol" FontSize="13"
                                        MinWidth="34" Margin="0,0,4,0" />
                                <Button x:Name="HDTPartitionDownButton" Content="&#xE011;"
                                        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>