Templates/Wizard/ComputerDetail.xaml

<!--
    A PREVIEW PAGE, NOT A PRODUCT ONE. See HDTPreviewTaskSequence.xaml.
 
    MDT'S "COMPUTER DETAILS" PANE, and the shape is deliberate: an MDT admin
    knows this screen. The name and the domain-or-workgroup choice sit together
    because they are one decision about a machine's identity, and MDT has
    carried them together since LiteTouch.
 
    TWO HALVES, TWO SKIP KEYS. HDTSkipComputerName hides the top half and
    HDTSkipDomainMembership the bottom - MDT has both properties for this one
    pane, and the pane mechanism the host already has (Get-HDTWizardSkip returns
    visibility by control name) is what collapses either.
 
    THE RADIO DECIDES DECLARATIVELY. There is no code-behind in WinPE, so which
    boxes are enabled follows the radio through a DataTrigger, exactly as
    HDTTheme.xaml's address boxes follow the DHCP/static radio.
-->
<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
 
    <!-- ============ the name ============ -->
    <StackPanel Grid.Row="0" x:Name="HDTComputerNamePane">
        <TextBlock Text="Computer name" Foreground="#FFCCCCCC" FontSize="14" Margin="0,0,0,8" />
 
        <!--
            IT SETS NO FONT, NO PADDING AND NO COLOUR. HDTTheme.xaml's TextBox
            style sets Height="32" with FontSize="15", and a LOCAL VALUE BEATS A
            STYLE SETTER - so a page that set its own font and padding grew the
            text inside a box that stayed 32px tall and clipped the bottom three
            pixels. The underscore lives entirely in those three pixels, so the
            box appeared to be dropping the character rather than cutting the
            bottom off it.
        -->
        <TextBox x:Name="HDTComputerNameBox" Text="" MaxLength="15"
                 Width="380" HorizontalAlignment="Left" />
 
        <!--
            ONE LINE, NOT A PANEL. This page carried a three-row box explaining
            the length limit, the ten forbidden characters and the DNS warning -
            and it pushed the workgroup option off the bottom of the window,
            which is the choice most machines take. A screen that explains a
            rule at the cost of hiding a control has the trade backwards.
 
            THE RULES STILL REACH THE TECHNICIAN, LATER AND ONLY WHEN THEY
            MATTER: an illegal character cannot be typed at all, and a name that
            is too long or not DNS-safe puts the reason on the message line at
            the bottom of the shell, in red or amber. That is the moment the
            explanation is worth reading. Before then it is a wall of text
            between a technician and a text box.
        -->
        <TextBlock Foreground="#FF8A8A8A" FontSize="12" TextWrapping="Wrap"
                   MaxWidth="560" HorizontalAlignment="Left" Margin="0,8,0,0"
                   Text="1 to 15 characters. Letters, digits and hyphens are safest - anything else is allowed but is not a valid DNS name. These cannot be typed: . \ / : * ? &quot; &lt; &gt; | or spaces." />
    </StackPanel>
 
    <!-- ============ the domain or the workgroup ============ -->
    <StackPanel Grid.Row="1" x:Name="HDTDomainPane" Margin="0,24,0,0">
        <TextBlock Text="Join a domain or a workgroup" Foreground="#FFCCCCCC" FontSize="14" Margin="0,0,0,10" />
 
        <RadioButton x:Name="HDTJoinDomainRadio" GroupName="HDTMembership" Content="Join a domain" />
 
        <!--
            THE DISTINCTION THAT COSTS PEOPLE AN AFTERNOON, SAID ON THE SCREEN.
            "Domain to join" is where the MACHINE goes; the account below is WHO
            puts it there, and it frequently lives somewhere else.
        -->
        <TextBlock Text="The machine joins the domain below. The account is who creates its computer object - often from a different domain, and never the account that reaches the deployment share."
                   Foreground="#FF8A8A8A" FontSize="12" TextWrapping="Wrap"
                   MaxWidth="520" HorizontalAlignment="Left" Margin="24,6,0,0" />
 
        <Grid Margin="24,10,0,0">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="120" />
                <ColumnDefinition Width="Auto" />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
 
            <TextBlock Grid.Row="0" Grid.Column="0" Text="Domain to join" Foreground="#FF8A8A8A"
                       FontSize="13" VerticalAlignment="Center" Margin="0,0,0,8"
                       ToolTip="The domain THIS MACHINE joins - for example corp.contoso.com." />
            <TextBox Grid.Row="0" Grid.Column="1" x:Name="HDTJoinDomainBox" Width="380"
                     HorizontalAlignment="Left" Margin="0,0,0,8">
                <TextBox.Style>
                    <Style TargetType="TextBox">
                        <Setter Property="IsEnabled" Value="False" />
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding IsChecked, ElementName=HDTJoinDomainRadio}" Value="True">
                                <Setter Property="IsEnabled" Value="True" />
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </TextBox.Style>
            </TextBox>
 
            <!--
                THE OU IS OPTIONAL AND SAYS SO. Left empty, the machine account
                lands in the domain's default container - which is a decision
                somebody made once and nobody remembers, so it is worth stating
                on the screen rather than in a document.
            -->
            <TextBlock Grid.Row="1" Grid.Column="0" Text="OU (optional)" Foreground="#FF8A8A8A"
                       FontSize="13" VerticalAlignment="Center" Margin="0,0,0,8" />
            <TextBox Grid.Row="1" Grid.Column="1" x:Name="HDTMachineObjectOuBox" Width="380"
                     HorizontalAlignment="Left" Margin="0,0,0,8">
                <TextBox.Style>
                    <Style TargetType="TextBox">
                        <Setter Property="IsEnabled" Value="False" />
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding IsChecked, ElementName=HDTJoinDomainRadio}" Value="True">
                                <Setter Property="IsEnabled" Value="True" />
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </TextBox.Style>
            </TextBox>
 
            <!--
                THE ACCOUNT THAT PERFORMS THE JOIN. MDT's DomainAdmin,
                DomainAdminDomain and DomainAdminPassword; HDT already carries
                all three in Get-HDTVariableMap. Nothing can join a domain
                without them, so a page that asked for a domain and not for
                these would collect an answer that cannot be acted on.
 
                IT IS NOT THE SHARE ACCOUNT. The Welcome screen's credential
                reaches the deployment share; this one has rights in the
                directory. They are frequently different accounts, and
                conflating them is how a deployment reaches its content and
                then cannot join.
            -->
            <!--
                ONE BOX, TYPED THE WAY WINDOWS PROMPTS FOR IT. This was two -
                the account and the domain it lives in - because that is how
                MDT's variables are shaped. A technician joining a domain does
                not think in two boxes; they think CORP\svc-hdt-join.
 
                MDT KEEPS A SEPARATE DOMAIN BOX AND SO DOES THIS PAGE - it is
                the pane an MDT admin already knows, and this file follows it.
                What the split adds is that BOTH WAYS OF SAYING IT WORK: type
                CORP\svc-hdt-join and leave the box empty, or type svc-hdt-join
                and fill the box, and HDTDomainAdmin and HDTDomainAdminDomain
                come out the same either way.
 
                PRECEDENCE, MOST SPECIFIC FIRST: a DOMAIN\ prefix wins over the
                box, the box wins over the domain being joined. The first of
                those follows the rule Get-HDTWizardCredential already set - "a
                UserID that already carries a domain is left alone" - so
                'CORP\svc' never becomes 'CORP\CORP\svc'.
            -->
            <TextBlock Grid.Row="2" Grid.Column="0" Text="Join account" Foreground="#FF8A8A8A"
                       FontSize="13" VerticalAlignment="Center" Margin="0,0,0,8"
                       ToolTip="The user with rights to create the computer object. NOT the account that reaches the deployment share." />
            <TextBox Grid.Row="2" Grid.Column="1" x:Name="HDTDomainAdminBox" Width="380"
                     HorizontalAlignment="Left" Margin="0,0,0,8"
                     ToolTip="CORP\svc-hdt-join, or svc-hdt-join@corp.contoso.com. A bare name means an account in the domain being joined.">
                <TextBox.Style>
                    <Style TargetType="TextBox">
                        <Setter Property="IsEnabled" Value="False" />
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding IsChecked, ElementName=HDTJoinDomainRadio}" Value="True">
                                <Setter Property="IsEnabled" Value="True" />
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </TextBox.Style>
            </TextBox>
 
            <!--
                HDTPasswordBox / HDTPasswordRevealBox / HDTPasswordRevealToggle
                ARE THE NAMES THE HOST ALREADY WIRES. PasswordBox.Password is
                not a DependencyProperty - it cannot be bound, styled or
                DataTriggered, and there is no code-behind to reveal it - so the
                markup carries two boxes in one cell and New-HDTWizardHost swaps
                which is visible, copying the text across. Using the names it
                looks for is what gets the eye for nothing.
 
                THE PASSWORD NEVER REACHES THE SUMMARY. Its Collect declaration
                is marked IsSecret, so the summary row reads "(set, not shown)"
                and the rules.yaml snippet names it in a comment and writes no
                value - a screen somebody photographs and a file on a share are
                both worse places for it than a log, and the variable map
                already says it is never written to one.
            -->
            <TextBlock Grid.Row="3" Grid.Column="0" Text="Password" Foreground="#FF8A8A8A"
                       FontSize="13" VerticalAlignment="Center" Margin="0,0,0,8" />
            <Grid Grid.Row="3" Grid.Column="1" Margin="0,0,0,8">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="380" />
                    <ColumnDefinition Width="Auto" />
                </Grid.ColumnDefinitions>
 
                <PasswordBox Grid.Column="0" x:Name="HDTPasswordBox" HorizontalAlignment="Left" Width="380">
                    <PasswordBox.Style>
                        <Style TargetType="PasswordBox">
                            <Setter Property="IsEnabled" Value="False" />
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding IsChecked, ElementName=HDTJoinDomainRadio}" Value="True">
                                    <Setter Property="IsEnabled" Value="True" />
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </PasswordBox.Style>
                </PasswordBox>
 
                <TextBox Grid.Column="0" x:Name="HDTPasswordRevealBox" Width="380"
                         HorizontalAlignment="Left" Visibility="Collapsed" />
 
                <ToggleButton Grid.Column="1" x:Name="HDTPasswordRevealToggle" Content="&#x1F441;"
                              Width="36" Height="32" Margin="8,0,0,0"
                              Background="#FF3A3A3C" Foreground="White" BorderThickness="0"
                              ToolTip="Show the password" />
            </Grid>
 
            <!--
                THE ACCOUNT'S OWN DOMAIN, WHERE MDT PUTS IT - under the
                password, and labelled just "Domain" there. It is labelled
                "Account's domain" here because the pane already has a "Domain
                to join" four rows up and two boxes called Domain on one screen
                is how the wrong one gets filled in.
 
                OPTIONAL, AND THE HINT SAYS WHAT HAPPENS WHEN IT IS EMPTY. A
                required-looking box that can be left blank is a box a
                technician fills in with a guess.
            -->
            <TextBlock Grid.Row="4" Grid.Column="0" Text="Account's domain" Foreground="#FF8A8A8A"
                       FontSize="13" VerticalAlignment="Center"
                       ToolTip="Where the join account lives. Leave empty and the domain being joined is used." />
            <StackPanel Grid.Row="4" Grid.Column="1">
                <TextBox x:Name="HDTDomainAdminDomainBox" Width="380" HorizontalAlignment="Left"
                         ToolTip="For example CORP. Leave empty to use the domain being joined, or type CORP\svc-hdt-join in the account box instead.">
                    <TextBox.Style>
                        <Style TargetType="TextBox">
                            <Setter Property="IsEnabled" Value="False" />
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding IsChecked, ElementName=HDTJoinDomainRadio}" Value="True">
                                    <Setter Property="IsEnabled" Value="True" />
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </TextBox.Style>
                </TextBox>
 
                <TextBlock Text="Empty means the domain being joined. A DOMAIN\user in the account box wins over this."
                           Foreground="#FF8A8A8A" FontSize="12" TextWrapping="Wrap"
                           MaxWidth="380" HorizontalAlignment="Left" Margin="0,6,0,0" />
            </StackPanel>
        </Grid>
 
        <RadioButton x:Name="HDTJoinWorkgroupRadio" GroupName="HDTMembership"
                     Content="Join a workgroup" IsChecked="True" Margin="0,16,0,0" />
 
        <Grid Margin="24,10,0,0">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="120" />
                <ColumnDefinition Width="Auto" />
            </Grid.ColumnDefinitions>
 
            <TextBlock Grid.Column="0" Text="Workgroup" Foreground="#FF8A8A8A"
                       FontSize="13" VerticalAlignment="Center" />
            <TextBox Grid.Column="1" x:Name="HDTJoinWorkgroupBox" Text="WORKGROUP" MaxLength="15"
                     Width="380" HorizontalAlignment="Left">
                <TextBox.Style>
                    <Style TargetType="TextBox">
                        <Setter Property="IsEnabled" Value="False" />
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding IsChecked, ElementName=HDTJoinWorkgroupRadio}" Value="True">
                                <Setter Property="IsEnabled" Value="True" />
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </TextBox.Style>
            </TextBox>
        </Grid>
    </StackPanel>
 
    <!--
        THE THIRD ROW IS DELIBERATELY EMPTY. It used to hold a panel explaining
        what a computer name may contain - three rows, a heading and a border -
        and it pushed "Join a workgroup" off the bottom of the window, which is
        the option most machines take.
 
        A SCREEN THAT EXPLAINS A RULE AT THE COST OF HIDING A CONTROL HAS THE
        TRADE BACKWARDS. The rules did not go anywhere: an illegal character
        cannot be typed at all, a name that is too long or not DNS-safe puts the
        reason on the shell's message line in red or amber, and the one-line
        hint under the name box says the rest. Each of those arrives at the
        moment it is worth reading, rather than as a wall of text between a
        technician and a text box.
 
        The row stays in the layout so the panes above it keep their spacing
        when the window is taller than they are.
    -->
</Grid>