UI/Console/HDTSelectionProfile.xaml
|
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Selection profiles" Height="720" Width="1120" MinHeight="480" MinWidth="860" WindowStartupLocation="Manual" Background="{DynamicResource HDTWindowBrush}"> <!-- THE SELECTION PROFILES WINDOW - Deployment Workbench's Advanced Configuration \ Selection Profiles, which is where an MDT admin has defined "which folders does this thing use" for fifteen years. IT IS A WINDOW AND NOT A TAB ON THE BOOT IMAGE, and that is deliberate. A profile is SHARE-WIDE: DESIGN 13 calls standalone media a content projection of the share, and a selection profile is that projection's filter, so the same document that picks two vendor WinPE packs for a boot image picks which applications go on a USB stick. Hanging it off the boot image would say it was about drivers, and then the media code would need a second one. THE TREE IS TICK BOXES BECAUSE AN ADMINISTRATOR KNOWS THE FOLDER BY SEEING IT. That is MDT's control here, and the reason a profile's include list is a set of paths rather than a pattern: the thing being chosen is on the screen. THE SQUARE IS THE CONTROL THAT MATTERS. Drivers ticked is the whole store - six hundred .inf files in a boot image that is transferred to every machine that PXE boots. Drivers SQUARE, with two vendor packs ticked below it, is a hundred. A two-state box cannot tell those apart without opening every branch. NOTHING ON THIS WINDOW EXISTS WITHOUT A COMMAND BEHIND IT: Profiles list Get-HDTSelectionProfile New New-HDTSelectionProfile Rename Set-HDTSelectionProfile -Name Delete Remove-HDTSelectionProfile The tree Get-HDTShareContentFolder Save Set-HDTSelectionProfile -Include, Save-HDTSelectionProfileDocument NO x:Class AND NO CODE-BEHIND, as HDTConsole.xaml and HDTBootImage.xaml. Handlers attach in PowerShell, by name. NAMED CONTROLS ARE THE CONTRACT with New-HDTConsoleHost: HDTSelectionProfileTitleText, HDTSelectionProfilePathText, HDTSelectionProfileListLabel, HDTSelectionProfileList, HDTSelectionProfileNewButton, HDTSelectionProfileRenameButton, HDTSelectionProfileDeleteButton, HDTSelectionProfileIncludeLabel, HDTSelectionProfileIncludeHint, HDTSelectionProfileTree, HDTSelectionProfileSummaryText, HDTSelectionProfileCommandText, HDTSelectionProfileSaveButton and HDTSelectionProfileCloseButton. THE PALETTE IS THE CONSOLE'S - every colour a DynamicResource under the keys HDTConsole.xaml declares, so Get-HDTConsoleTheme repaints this window with the others. --> <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="HDTHintBrush" Color="#FF6A6A6A" /> <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. --> <!-- THE ? THIS PRODUCT ALREADY HAS, copied verbatim from HDTNewWorkspace.xaml, which shares it with HDTNewSequence, HDTImportApplication, HDTApplicationDetection, HDTConsole and HDTSequenceEditor. A 22px outlined dot with a bold glyph and a help cursor - not a solid button, which is what this tab first got and what made it read as a different kind of control. --> <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="8,0,0,10" /> <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 HDTHintTextBrush}" /> <Setter Property="FontSize" Value="12" /> <Setter Property="FontWeight" Value="Bold" /> <Setter Property="HorizontalAlignment" Value="Center" /> <Setter Property="VerticalAlignment" Value="Center" /> </Style> <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 means 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> <Style TargetType="TextBlock"> <Setter Property="Foreground" Value="{DynamicResource HDTPanelTextBrush}" /> <Setter Property="FontFamily" Value="Segoe UI" /> <Setter Property="FontSize" Value="13" /> </Style> <!-- The hint under a field: the same size, deliberately quieter. It says what an EMPTY box means, which is the question every one of these fields raises and none of them can answer by itself. --> <Style x:Key="HDTHintText" TargetType="TextBlock"> <Setter Property="Foreground" Value="{DynamicResource HDTHintBrush}" /> <Setter Property="FontFamily" Value="Segoe UI" /> <Setter Property="FontSize" Value="12" /> <Setter Property="TextWrapping" Value="Wrap" /> </Style> <!-- WHITE, BECAUSE THESE ARE TYPED INTO. HDTFieldBrush is the read-only wash the console's detail pane puts on rows that are a reading rather than a setting; every box on this window is a setting. It wore the wash for months and nobody could tell, because the wash was #FAFAFA and invisible against white - the moment it became a grey somebody could see, this window started claiming its image name could not be changed. --> <Style TargetType="TextBox"> <Setter Property="Background" Value="{DynamicResource HDTPanelBrush}" /> <Setter Property="Foreground" Value="{DynamicResource HDTPanelTextBrush}" /> <Setter Property="BorderBrush" Value="{DynamicResource HDTBorderBrush}" /> <Setter Property="BorderThickness" Value="1" /> <Setter Property="FontFamily" Value="Segoe UI" /> <Setter Property="FontSize" Value="13" /> <Setter Property="Padding" Value="6,4,6,4" /> </Style> <Style TargetType="ComboBox"> <Setter Property="FontFamily" Value="Segoe UI" /> <!-- AND IT MUST NOT LOOK READ-ONLY. WPF's default ComboBox template paints its own grey chrome and ignores Background, so a dropdown beside white boxes reads as a disabled one. IsEditable puts a real text box in the closed control, which takes the Background; IsReadOnly keeps it from being typed into. No ComboBox here uses an ItemTemplate, so what it shows is what it showed before. --> <Setter Property="IsEditable" Value="True" /> <Setter Property="IsReadOnly" Value="True" /> <Setter Property="Background" Value="{DynamicResource HDTPanelBrush}" /> <Setter Property="Foreground" Value="{DynamicResource HDTPanelTextBrush}" /> <Setter Property="BorderBrush" Value="{DynamicResource HDTBorderBrush}" /> <Setter Property="BorderThickness" Value="1" /> <Setter Property="FontSize" Value="13" /> <Setter Property="Padding" Value="6,4,6,4" /> </Style> <Style TargetType="CheckBox"> <Setter Property="Foreground" Value="{DynamicResource HDTPanelTextBrush}" /> <Setter Property="FontFamily" Value="Segoe UI" /> <Setter Property="FontSize" Value="13" /> </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="*" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <!-- the banner: which share these profiles belong to --> <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="HDTSelectionProfileTitleText" Foreground="{DynamicResource HDTBannerTextBrush}" FontFamily="Segoe UI" FontSize="19" /> <TextBlock Grid.Row="1" x:Name="HDTSelectionProfilePathText" Text="" Foreground="{DynamicResource HDTBannerLabelBrush}" FontFamily="Consolas, Courier New" FontSize="12" Margin="0,4,0,0" /> </Grid> </Border> <Grid Grid.Row="1" Margin="24,18,24,0"> <Grid.ColumnDefinitions> <ColumnDefinition Width="300" /> <ColumnDefinition Width="18" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <!-- ================= the profiles themselves ================= --> <Grid Grid.Column="0"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <TextBlock Grid.Row="0" x:Name="HDTSelectionProfileListLabel" Margin="0,0,0,6" Foreground="{DynamicResource HDTLabelBrush}" FontWeight="SemiBold" /> <Border Grid.Row="1" Background="{DynamicResource HDTPanelBrush}" BorderBrush="{DynamicResource HDTBorderBrush}" BorderThickness="1"> <ListBox x:Name="HDTSelectionProfileList" BorderThickness="0" Padding="4" Background="Transparent"> <ListBox.ItemTemplate> <DataTemplate> <!-- THE NAME, THEN WHAT IT CARRIES. A list of names alone makes an administrator click each one to find out which is the empty profile they started on Tuesday. --> <StackPanel Margin="4,4,4,4"> <TextBlock Text="{Binding Name}" /> <TextBlock Text="{Binding Detail}" FontSize="11" Foreground="{DynamicResource HDTHintBrush}" /> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </Border> <!-- THE BUILT-INS ARE IN THE LIST AND CANNOT BE DELETED. MDT ships Everything, All Drivers and Nothing and so does this; they resolve by name with no document behind them, so a hand-made share with no selection-profiles.yaml still has something the boot image can point at. Rename and Delete go grey on one rather than refusing after the click. --> <StackPanel Grid.Row="2" Margin="0,10,0,0"> <!-- THE NAME IS TYPED HERE, NOT IN A SECOND WINDOW. New and Rename both need one, and a modal that asks for a single string is a window an administrator has to dismiss before they can see the tree they are naming. THE ID IS DERIVED FROM IT AND SHOWN. workspace.yaml references the id, so an administrator who has to write one into a document by hand needs to be able to read it off the screen - and a derived id nobody could see would be a value that appears in a file from nowhere. --> <TextBlock x:Name="HDTSelectionProfileNameLabel" Margin="0,0,0,4" /> <TextBox x:Name="HDTSelectionProfileNameBox" /> <TextBlock x:Name="HDTSelectionProfileIdText" Style="{StaticResource HDTHintText}" Margin="0,4,0,0" /> <StackPanel Orientation="Horizontal" Margin="0,10,0,0"> <Button x:Name="HDTSelectionProfileNewButton" MinWidth="76" /> <Button x:Name="HDTSelectionProfileRenameButton" MinWidth="76" /> <Button x:Name="HDTSelectionProfileDeleteButton" MinWidth="76" Margin="0" /> </StackPanel> </StackPanel> </Grid> <!-- ================= what the profile includes ================= --> <Grid Grid.Column="2"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <TextBlock Grid.Row="0" x:Name="HDTSelectionProfileIncludeLabel" Margin="0,0,0,6" Foreground="{DynamicResource HDTLabelBrush}" FontWeight="SemiBold" /> <TextBlock Grid.Row="1" x:Name="HDTSelectionProfileIncludeHint" Style="{StaticResource HDTHintText}" Margin="0,0,0,8" MaxWidth="700" HorizontalAlignment="Left" /> <Border Grid.Row="2" Background="{DynamicResource HDTPanelBrush}" BorderBrush="{DynamicResource HDTBorderBrush}" BorderThickness="1"> <TreeView x:Name="HDTSelectionProfileTree" BorderThickness="0" Padding="8" Background="Transparent"> <!-- THE BRANCH THAT LEADS TO A TICK OPENS ITSELF, which is what IsExpanded on the row is for. A window that came up with everything shut would hide the ticks that are the reason it was opened. --> <TreeView.ItemContainerStyle> <Style TargetType="TreeViewItem"> <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" /> </Style> </TreeView.ItemContainerStyle> <TreeView.ItemTemplate> <HierarchicalDataTemplate ItemsSource="{Binding Children}"> <StackPanel Orientation="Horizontal" Margin="0,2,0,2"> <!-- IsThreeState, AND THE THIRD STATE IS THE POINT. Drivers ticked is the whole store; Drivers SQUARE with two vendor packs below it is a hundred .inf files. A two-state box cannot tell those apart without opening every branch. --> <!-- IsThreeState is FALSE and the square still appears. A null IsChecked draws the square whatever this says; what IsThreeState="True" adds is the USER cycling into it - ticked, square, clear - and "some of Drivers" is not something anybody can mean by clicking. It is computed, from what is ticked below. --> <CheckBox IsThreeState="False" IsChecked="{Binding State, Mode=TwoWay}" VerticalAlignment="Center" /> <TextBlock Text="{Binding Name}" Margin="6,0,0,0" VerticalAlignment="Center" /> <TextBlock Text="{Binding Detail}" Margin="12,0,0,0" FontSize="11" VerticalAlignment="Center" Foreground="{DynamicResource HDTHintBrush}" /> </StackPanel> </HierarchicalDataTemplate> </TreeView.ItemTemplate> </TreeView> </Border> <TextBlock Grid.Row="3" x:Name="HDTSelectionProfileSummaryText" Style="{StaticResource HDTHintText}" Margin="0,8,0,0" MaxWidth="700" HorizontalAlignment="Left" /> </Grid> </Grid> <Grid Grid.Row="2" 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"> <!-- AcceptsReturn, ON A BOX NOBODY TYPES INTO. One press of Save is two invocations - the splice and the write - and a TextBox without this shows the first and silently eats the second. --> <TextBox x:Name="HDTSelectionProfileCommandText" Text="" IsReadOnly="True" BorderThickness="0" AcceptsReturn="True" MaxHeight="76" VerticalScrollBarVisibility="Auto" Background="Transparent" Foreground="{DynamicResource HDTCommandTextBrush}" FontFamily="Consolas, Courier New" FontSize="12" TextWrapping="Wrap" /> </Border> <Grid Grid.Row="1" Margin="0,14,0,0"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <StackPanel Grid.Column="1" Orientation="Horizontal"> <Button x:Name="HDTSelectionProfileSaveButton" MinWidth="96" /> <Button x:Name="HDTSelectionProfileCloseButton" MinWidth="96" Margin="0" /> </StackPanel> </Grid> </Grid> </Grid> </Window> |