feat(01-06): build WPF shell — MainWindow XAML, ViewModels, LogPanelSink wiring
- Add FeatureTabBase UserControl with ProgressBar/TextBlock/CancelButton strip (Visibility bound to IsRunning, shown only during operations) - Add MainWindowViewModel with TenantProfiles ObservableCollection, ConnectCommand, ClearSessionCommand, ManageProfilesCommand, ProgressUpdatedMessage subscription - Add ProfileManagementViewModel wrapping ProfileService CRUD with input validation - Add SettingsViewModel (extends FeatureViewModelBase) with language/folder settings - Update MainWindow.xaml: DockPanel shell with Toolbar, TabControl (8 tabs), 150px RichTextBox LogPanel, StatusBar (tenant name | ProgressStatus | ProgressPercentage) - MainWindow.xaml.cs: DI constructor, DataContext=viewModel, LoadProfilesAsync on Loaded - App.xaml.cs: register all services, wire LogPanelSink after MainWindow resolved, register DispatcherUnhandledException and UnobservedTaskException global handlers - App.xaml: add BoolToVisibilityConverter resource
This commit is contained in:
@@ -1,12 +1,71 @@
|
||||
<Window x:Class="SharepointToolbox.MainWindow"
|
||||
<Window x:Class="SharepointToolbox.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:SharepointToolbox"
|
||||
xmlns:loc="clr-namespace:SharepointToolbox.Localization"
|
||||
xmlns:controls="clr-namespace:SharepointToolbox.Views.Controls"
|
||||
mc:Ignorable="d"
|
||||
Title="MainWindow" Height="450" Width="800">
|
||||
<Grid>
|
||||
Title="{Binding Source={x:Static loc:TranslationSource.Instance}, Path=[app.title]}"
|
||||
MinWidth="900" MinHeight="600" Height="700" Width="1100">
|
||||
<DockPanel>
|
||||
<!-- Toolbar -->
|
||||
<ToolBar DockPanel.Dock="Top">
|
||||
<ComboBox Width="220" ItemsSource="{Binding TenantProfiles}"
|
||||
SelectedItem="{Binding SelectedProfile}"
|
||||
DisplayMemberPath="Name" />
|
||||
<Button Content="{Binding Source={x:Static loc:TranslationSource.Instance}, Path=[toolbar.connect]}"
|
||||
Command="{Binding ConnectCommand}" />
|
||||
<Button Content="{Binding Source={x:Static loc:TranslationSource.Instance}, Path=[toolbar.manage]}"
|
||||
Command="{Binding ManageProfilesCommand}" />
|
||||
<Separator />
|
||||
<Button Content="{Binding Source={x:Static loc:TranslationSource.Instance}, Path=[toolbar.clear]}"
|
||||
Command="{Binding ClearSessionCommand}" />
|
||||
</ToolBar>
|
||||
|
||||
</Grid>
|
||||
<!-- StatusBar: tenant name | operation status text | progress % -->
|
||||
<StatusBar DockPanel.Dock="Bottom" Height="24">
|
||||
<StatusBarItem Content="{Binding SelectedProfile.Name}" />
|
||||
<Separator />
|
||||
<StatusBarItem Content="{Binding ProgressStatus}" />
|
||||
<Separator />
|
||||
<StatusBarItem Content="{Binding ProgressPercentage, StringFormat={}{0}%}" />
|
||||
</StatusBar>
|
||||
|
||||
<!-- Log Panel -->
|
||||
<RichTextBox x:Name="LogPanel" DockPanel.Dock="Bottom" Height="150"
|
||||
IsReadOnly="True" VerticalScrollBarVisibility="Auto"
|
||||
Background="Black" Foreground="LimeGreen"
|
||||
FontFamily="Consolas" FontSize="11" />
|
||||
|
||||
<!-- TabControl: 7 stub tabs use FeatureTabBase; Settings tab wired in plan 01-07 -->
|
||||
<TabControl>
|
||||
<TabItem Header="{Binding Source={x:Static loc:TranslationSource.Instance}, Path=[tab.permissions]}">
|
||||
<controls:FeatureTabBase />
|
||||
</TabItem>
|
||||
<TabItem Header="{Binding Source={x:Static loc:TranslationSource.Instance}, Path=[tab.storage]}">
|
||||
<controls:FeatureTabBase />
|
||||
</TabItem>
|
||||
<TabItem Header="{Binding Source={x:Static loc:TranslationSource.Instance}, Path=[tab.search]}">
|
||||
<controls:FeatureTabBase />
|
||||
</TabItem>
|
||||
<TabItem Header="{Binding Source={x:Static loc:TranslationSource.Instance}, Path=[tab.duplicates]}">
|
||||
<controls:FeatureTabBase />
|
||||
</TabItem>
|
||||
<TabItem Header="{Binding Source={x:Static loc:TranslationSource.Instance}, Path=[tab.templates]}">
|
||||
<controls:FeatureTabBase />
|
||||
</TabItem>
|
||||
<TabItem Header="{Binding Source={x:Static loc:TranslationSource.Instance}, Path=[tab.bulk]}">
|
||||
<controls:FeatureTabBase />
|
||||
</TabItem>
|
||||
<TabItem Header="{Binding Source={x:Static loc:TranslationSource.Instance}, Path=[tab.structure]}">
|
||||
<controls:FeatureTabBase />
|
||||
</TabItem>
|
||||
<!-- Settings tab: placeholder TextBlock replaced by SettingsView in plan 01-07 -->
|
||||
<TabItem x:Name="SettingsTabItem"
|
||||
Header="{Binding Source={x:Static loc:TranslationSource.Instance}, Path=[tab.settings]}">
|
||||
<TextBlock Text="Settings (plan 01-07)" HorizontalAlignment="Center" VerticalAlignment="Center" />
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
</DockPanel>
|
||||
</Window>
|
||||
|
||||
Reference in New Issue
Block a user