diff --git a/src/UniGetUI.Avalonia/App.axaml.cs b/src/UniGetUI.Avalonia/App.axaml.cs index 52ca50067..6abd79e4e 100644 --- a/src/UniGetUI.Avalonia/App.axaml.cs +++ b/src/UniGetUI.Avalonia/App.axaml.cs @@ -1,10 +1,8 @@ using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.IO; using Avalonia; using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Markup.Xaml; -using Avalonia.Markup.Xaml.Styling; using Avalonia.Platform; using Avalonia.Styling; using Avalonia.Threading; @@ -23,25 +21,12 @@ namespace UniGetUI.Avalonia; public partial class App : Application { - [UnconditionalSuppressMessage( - "Trimming", - "IL2026", - Justification = "Platform theme dictionaries are Avalonia resources included in the app package; only the resource URI is selected dynamically.")] public override void Initialize() { AvaloniaXamlLoader.Load(this); #if AVALONIA_DIAGNOSTICS_ENABLED this.AttachDeveloperTools(); #endif - - string platform = OperatingSystem.IsWindows() ? "Windows" - : OperatingSystem.IsMacOS() ? "macOS" - : "Linux"; - - Styles.Add(new StyleInclude(new Uri("avares://UniGetUI.Avalonia/")) - { - Source = new Uri($"avares://UniGetUI.Avalonia/Assets/Styles/Styles.{platform}.axaml") - }); } public override void OnFrameworkInitializationCompleted() diff --git a/src/UniGetUI.Avalonia/Assets/Styles/Styles.Common.axaml b/src/UniGetUI.Avalonia/Assets/Styles/Styles.Common.axaml index d8c151aca..65ab004ad 100644 --- a/src/UniGetUI.Avalonia/Assets/Styles/Styles.Common.axaml +++ b/src/UniGetUI.Avalonia/Assets/Styles/Styles.Common.axaml @@ -2,8 +2,155 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:controls="using:UniGetUI.Avalonia.Views.Controls"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniGetUI.Avalonia/Assets/Styles/Styles.Linux.axaml b/src/UniGetUI.Avalonia/Assets/Styles/Styles.Linux.axaml deleted file mode 100644 index 5364da18e..000000000 --- a/src/UniGetUI.Avalonia/Assets/Styles/Styles.Linux.axaml +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/UniGetUI.Avalonia/Assets/Styles/Styles.Windows.axaml b/src/UniGetUI.Avalonia/Assets/Styles/Styles.Windows.axaml deleted file mode 100644 index 6154a9ddb..000000000 --- a/src/UniGetUI.Avalonia/Assets/Styles/Styles.Windows.axaml +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/UniGetUI.Avalonia/Assets/Styles/Styles.macOS.axaml b/src/UniGetUI.Avalonia/Assets/Styles/Styles.macOS.axaml deleted file mode 100644 index 8d2909c11..000000000 --- a/src/UniGetUI.Avalonia/Assets/Styles/Styles.macOS.axaml +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/UniGetUI.Avalonia/Models/PackageCollections.cs b/src/UniGetUI.Avalonia/Models/PackageCollections.cs index 21b45e931..125c99342 100644 --- a/src/UniGetUI.Avalonia/Models/PackageCollections.cs +++ b/src/UniGetUI.Avalonia/Models/PackageCollections.cs @@ -296,6 +296,40 @@ public enum Sorter public Sorter CurrentSorter { get; private set; } = Sorter.Name; private bool _ascending = true; + /// Fires when any wrapper's IsChecked changes, or when items are added/removed. + public event EventHandler? SelectionStateChanged; + + public ObservablePackageCollection() + { + CollectionChanged += OnCollectionChanged; + } + + private void OnCollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) + { + if (e.OldItems is not null) + foreach (PackageWrapper w in e.OldItems) w.PropertyChanged -= OnWrapperPropertyChanged; + if (e.NewItems is not null) + foreach (PackageWrapper w in e.NewItems) w.PropertyChanged += OnWrapperPropertyChanged; + SelectionStateChanged?.Invoke(this, EventArgs.Empty); + } + + private void OnWrapperPropertyChanged(object? sender, PropertyChangedEventArgs e) + { + if (e.PropertyName == nameof(PackageWrapper.IsChecked)) + SelectionStateChanged?.Invoke(this, EventArgs.Empty); + } + + /// Returns the tri-state value for a "select-all" checkbox: true=all, false=none, null=some. + public bool? GetSelectionState() + { + if (Count == 0) return false; + int checkedCount = 0; + foreach (var w in this) if (w.IsChecked) checkedCount++; + if (checkedCount == 0) return false; + if (checkedCount == Count) return true; + return null; + } + public List GetPackages() => this.Select(w => w.Package).ToList(); diff --git a/src/UniGetUI.Avalonia/ViewModels/MainWindowViewModel.cs b/src/UniGetUI.Avalonia/ViewModels/MainWindowViewModel.cs index 34fcb3076..4b3ccba2d 100644 --- a/src/UniGetUI.Avalonia/ViewModels/MainWindowViewModel.cs +++ b/src/UniGetUI.Avalonia/ViewModels/MainWindowViewModel.cs @@ -127,6 +127,14 @@ private void OnPageViewModelPropertyChanged(object? sender, System.ComponentMode } } + // ─── Title bar ─────────────────────────────────────────────────────────── + // Mirrors WinUI behavior: the version appears next to "UniGetUI" only when + // the ShowVersionNumberOnTitlebar setting is enabled (the setting is gated + // on restart, so a one-shot read at construction is sufficient). + public string TitleBarText { get; } = Settings.Get(Settings.K.ShowVersionNumberOnTitlebar) + ? $"UniGetUI {CoreTools.Translate("version {0}", CoreData.VersionName)}" + : "UniGetUI"; + // ─── Banners ───────────────────────────────────────────────────────────── public InfoBarViewModel UpdatesBanner { get; } = new() { Severity = InfoBarSeverity.Success }; public InfoBarViewModel ErrorBanner { get; } = new() { Severity = InfoBarSeverity.Error }; diff --git a/src/UniGetUI.Avalonia/ViewModels/SoftwarePages/PackagesPageViewModel.cs b/src/UniGetUI.Avalonia/ViewModels/SoftwarePages/PackagesPageViewModel.cs index 8b6c0daac..310e46ea4 100644 --- a/src/UniGetUI.Avalonia/ViewModels/SoftwarePages/PackagesPageViewModel.cs +++ b/src/UniGetUI.Avalonia/ViewModels/SoftwarePages/PackagesPageViewModel.cs @@ -70,7 +70,16 @@ public class SourceTreeNode : INotifyPropertyChanged public string? PackageID { get; init; } public string? Version { get; init; } public string? Source { get; init; } - public AvaloniaList Children { get; } = new(); + public AvaloniaList Children { get; } + + public bool HasChildren => Children.Count > 0; + + public SourceTreeNode() + { + Children = new AvaloniaList(); + Children.CollectionChanged += (_, _) => + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(HasChildren))); + } public event PropertyChangedEventHandler? PropertyChanged; @@ -91,7 +100,21 @@ public bool IsExpanded public partial class PackagesPageViewModel : ViewModelBase { - public double FilterPaneColumnWidth => IsFilterPaneOpen ? 220.0 : 0.0; + // Live width of the filter pane. Code-behind keeps this in sync with the GridSplitter + // so the toolbar's main button (bound to FilterPaneColumnWidth) tracks resizes. + private double _trackedFilterPaneWidth = 220.0; + public double TrackedFilterPaneWidth + { + get => _trackedFilterPaneWidth; + set + { + if (Math.Abs(_trackedFilterPaneWidth - value) < 0.5) return; + _trackedFilterPaneWidth = value; + if (IsFilterPaneOpen) OnPropertyChanged(nameof(FilterPaneColumnWidth)); + } + } + + public double FilterPaneColumnWidth => IsFilterPaneOpen ? _trackedFilterPaneWidth : 0.0; partial void OnIsFilterPaneOpenChanged(bool value) { OnPropertyChanged(nameof(FilterPaneColumnWidth)); @@ -195,6 +218,11 @@ public PackagesPageViewModel(PackagesPageData data) SearchBoxPlaceholder = CoreTools.Translate("Search for packages"); AllPackagesChecked = data.PackagesAreCheckedByDefault; + FilteredPackages.SelectionStateChanged += (_, _) => + { + if (_suppressSelectionRecompute) return; + AllPackagesChecked = FilteredPackages.GetSelectionState(); + }; Loader = data.Loader; Loader.StartedLoading += Loader_StartedLoading; @@ -241,12 +269,12 @@ public Button AddToolbarButton(string svgName, string label, Action onClick, boo var icon = new SvgIcon { Path = $"avares://UniGetUI.Avalonia/Assets/Symbols/{svgName}.svg", - Width = 16, - Height = 16, + Width = 20, + Height = 20, VerticalAlignment = VerticalAlignment.Center, }; - var content = new StackPanel { Orientation = Orientation.Horizontal, Spacing = 4 }; + var content = new StackPanel { Orientation = Orientation.Horizontal, Spacing = 6 }; content.Children.Add(icon); if (showLabel) { @@ -260,8 +288,8 @@ public Button AddToolbarButton(string svgName, string label, Action onClick, boo var btn = new Button { - Height = 36, - Padding = new Thickness(8, 4), + Height = 40, + Padding = new Thickness(10, 4), CornerRadius = new CornerRadius(4), Content = content, }; @@ -275,13 +303,19 @@ public Button AddToolbarButton(string svgName, string label, Action onClick, boo /// Adds a thin vertical separator to the toolbar. public void AddToolbarSeparator() { + object? borderResource = null; + Application.Current?.Resources.TryGetResource( + "AppBorderBrush", + Application.Current?.ActualThemeVariant, + out borderResource); + var sep = new Separator { Width = 1, - Height = 30, + Height = 32, Margin = new Thickness(4, 4), - Background = Application.Current?.FindResource("AppBorderBrush") as IBrush - ?? new SolidColorBrush(Color.FromArgb(60, 255, 255, 255)), + Background = borderResource as IBrush + ?? new SolidColorBrush(Color.FromArgb(80, 128, 128, 128)), }; AutomationProperties.SetAccessibilityView(sep, AccessibilityView.Raw); ToolBarItems.Add(sep); @@ -559,10 +593,19 @@ partial void OnSearchModeChanged(SearchMode value) public bool SearchMode_Exact { get => SearchMode == SearchMode.Exact; set { if (value) SearchMode = SearchMode.Exact; } } public bool SearchMode_Similar { get => SearchMode == SearchMode.Similar; set { if (value) SearchMode = SearchMode.Similar; } } + private bool _suppressSelectionRecompute; partial void OnAllPackagesCheckedChanged(bool? value) { - if (value == true) FilteredPackages.SelectAll(); - else if (value == false) FilteredPackages.ClearSelection(); + _suppressSelectionRecompute = true; + try + { + if (value == true) FilteredPackages.SelectAll(); + else if (value == false) FilteredPackages.ClearSelection(); + } + finally + { + _suppressSelectionRecompute = false; + } } // ─── Sources ────────────────────────────────────────────────────────────── diff --git a/src/UniGetUI.Avalonia/Views/Controls/Settings/CheckboxButtonCard.cs b/src/UniGetUI.Avalonia/Views/Controls/Settings/CheckboxButtonCard.cs index 7cd29d8e6..c54a661a5 100644 --- a/src/UniGetUI.Avalonia/Views/Controls/Settings/CheckboxButtonCard.cs +++ b/src/UniGetUI.Avalonia/Views/Controls/Settings/CheckboxButtonCard.cs @@ -15,6 +15,9 @@ public sealed partial class CheckboxButtonCard : SettingsCard public ToggleSwitch _checkbox; public TextBlock _textblock; public Button Button; + private readonly TextBlock _stateLabel; + private static readonly string EnabledLabel = CoreTools.Translate("Enabled"); + private static readonly string DisabledLabel = CoreTools.Translate("Disabled"); private bool IS_INVERTED; private CoreSettings.K setting_name = CoreSettings.K.Unset; @@ -26,6 +29,7 @@ public CoreSettings.K SettingName IS_INVERTED = CoreSettings.ResolveKey(value).StartsWith("Disable"); _checkbox.IsChecked = CoreSettings.Get(setting_name) ^ IS_INVERTED ^ ForceInversion; _textblock.Opacity = (_checkbox.IsChecked ?? false) ? 1 : 0.7; + UpdateStateLabel(); Button.IsEnabled = (_checkbox.IsChecked ?? false) || _buttonAlwaysOn; } } @@ -70,10 +74,19 @@ public CheckboxButtonCard() Button = new Button { Margin = new Thickness(0, 8, 0, 0) }; _checkbox = new ToggleSwitch { + // OnContent/OffContent intentionally left null — state label is a + // sibling TextBlock to the LEFT of the knob. + OnContent = null, + OffContent = null, + VerticalAlignment = VerticalAlignment.Center, + }; + _stateLabel = new TextBlock + { + Text = DisabledLabel, + VerticalAlignment = VerticalAlignment.Center, Margin = new Thickness(0, 0, 8, 0), - OnContent = new TextBlock { Text = CoreTools.Translate("Enabled") }, - OffContent = new TextBlock { Text = CoreTools.Translate("Disabled") }, }; + AutomationProperties.SetAccessibilityView(_stateLabel, AccessibilityView.Raw); _textblock = new TextBlock { Margin = new Thickness(2, 0, 0, 0), @@ -84,7 +97,12 @@ public CheckboxButtonCard() IS_INVERTED = false; AutomationProperties.SetAccessibilityView(Button, AccessibilityView.Control); - Content = _checkbox; + Content = new StackPanel + { + Orientation = Orientation.Horizontal, + VerticalAlignment = VerticalAlignment.Center, + Children = { _stateLabel, _checkbox }, + }; Header = _textblock; Description = Button; @@ -94,6 +112,7 @@ public CheckboxButtonCard() StateChanged?.Invoke(this, EventArgs.Empty); Button.IsEnabled = (_checkbox.IsChecked ?? false) ? true : _buttonAlwaysOn; _textblock.Opacity = (_checkbox.IsChecked ?? false) ? 1 : 0.7; + UpdateStateLabel(); if (_textblock.Text is not null) { AccessibilityAnnouncementService.AnnounceToggle(_textblock.Text, _checkbox.IsChecked ?? false); @@ -102,4 +121,9 @@ public CheckboxButtonCard() Button.Click += (s, e) => Click?.Invoke(s, e); ApplyAutomationMetadata(_checkbox, _textblock.Text); } + + private void UpdateStateLabel() + { + _stateLabel.Text = (_checkbox.IsChecked ?? false) ? EnabledLabel : DisabledLabel; + } } diff --git a/src/UniGetUI.Avalonia/Views/Controls/Settings/CheckboxCard.cs b/src/UniGetUI.Avalonia/Views/Controls/Settings/CheckboxCard.cs index a1e24c950..cebe2c0eb 100644 --- a/src/UniGetUI.Avalonia/Views/Controls/Settings/CheckboxCard.cs +++ b/src/UniGetUI.Avalonia/Views/Controls/Settings/CheckboxCard.cs @@ -26,6 +26,9 @@ public ICommand? StateChangedCommand public ToggleSwitch _checkbox; public TextBlock _textblock; public TextBlock _warningBlock; + private readonly TextBlock _stateLabel; + private static readonly string EnabledLabel = CoreTools.Translate("Enabled"); + private static readonly string DisabledLabel = CoreTools.Translate("Disabled"); protected bool IS_INVERTED; private CoreSettings.K setting_name = CoreSettings.K.Unset; @@ -38,6 +41,7 @@ public CoreSettings.K SettingName IS_INVERTED = CoreSettings.ResolveKey(value).StartsWith("Disable"); _checkbox.IsChecked = CoreSettings.Get(setting_name) ^ IS_INVERTED ^ ForceInversion; _textblock.Opacity = (_checkbox.IsChecked ?? false) ? 1 : 0.7; + UpdateStateLabel(); _checkbox.IsCheckedChanged += _checkbox_Toggled; SyncToggleItemStatus(); } @@ -77,12 +81,21 @@ public CheckboxCard() { _checkbox = new ToggleSwitch { - Margin = new Thickness(0, 0, 8, 0), - OnContent = new TextBlock { Text = CoreTools.Translate("Enabled") }, - OffContent = new TextBlock { Text = CoreTools.Translate("Disabled") }, + // OnContent/OffContent intentionally left null — the state label is + // rendered as a sibling TextBlock to the LEFT of the knob below. + OnContent = null, + OffContent = null, + VerticalAlignment = VerticalAlignment.Center, }; // Force CheckBox role so macOS VoiceOver exposes checked/unchecked state AutomationProperties.SetControlTypeOverride(_checkbox, AutomationControlType.CheckBox); + _stateLabel = new TextBlock + { + Text = DisabledLabel, + VerticalAlignment = VerticalAlignment.Center, + Margin = new Thickness(0, 0, 8, 0), + }; + AutomationProperties.SetAccessibilityView(_stateLabel, AccessibilityView.Raw); _textblock = new TextBlock { VerticalAlignment = VerticalAlignment.Center, @@ -100,7 +113,12 @@ public CheckboxCard() IS_INVERTED = false; AutomationProperties.SetAccessibilityView(_warningBlock, AccessibilityView.Raw); - Content = _checkbox; + Content = new StackPanel + { + Orientation = Orientation.Horizontal, + VerticalAlignment = VerticalAlignment.Center, + Children = { _stateLabel, _checkbox }, + }; Header = new StackPanel { Spacing = 4, @@ -112,11 +130,17 @@ public CheckboxCard() ApplyAutomationMetadata(_checkbox, _textblock.Text); } + protected void UpdateStateLabel() + { + _stateLabel.Text = (_checkbox.IsChecked ?? false) ? EnabledLabel : DisabledLabel; + } + protected virtual void _checkbox_Toggled(object? sender, RoutedEventArgs e) { CoreSettings.Set(setting_name, (_checkbox.IsChecked ?? false) ^ IS_INVERTED ^ ForceInversion); StateChanged?.Invoke(this, EventArgs.Empty); _textblock.Opacity = (_checkbox.IsChecked ?? false) ? 1 : 0.7; + UpdateStateLabel(); SyncToggleItemStatus(); if (_textblock.Text is not null) { @@ -165,6 +189,7 @@ public string KeyName ^ IS_INVERTED ^ ForceInversion; _textblock.Opacity = (_checkbox.IsChecked ?? false) ? 1 : 0.7; + UpdateStateLabel(); _disableStateChangedEvent = false; SyncToggleItemStatus(); } @@ -184,6 +209,7 @@ public CoreSettings.K DictionaryName ^ IS_INVERTED ^ ForceInversion; _textblock.Opacity = (_checkbox.IsChecked ?? false) ? 1 : 0.7; + UpdateStateLabel(); SyncToggleItemStatus(); } } @@ -201,6 +227,7 @@ protected override void _checkbox_Toggled(object? sender, RoutedEventArgs e) ); StateChanged?.Invoke(this, EventArgs.Empty); _textblock.Opacity = (_checkbox.IsChecked ?? false) ? 1 : 0.7; + UpdateStateLabel(); SyncToggleItemStatus(); if (_textblock.Text is not null) { diff --git a/src/UniGetUI.Avalonia/Views/Controls/Settings/SecureCheckboxCard.cs b/src/UniGetUI.Avalonia/Views/Controls/Settings/SecureCheckboxCard.cs index 7332c4432..a0aa8e79d 100644 --- a/src/UniGetUI.Avalonia/Views/Controls/Settings/SecureCheckboxCard.cs +++ b/src/UniGetUI.Avalonia/Views/Controls/Settings/SecureCheckboxCard.cs @@ -25,6 +25,9 @@ public ICommand? StateChangedCommand public TextBlock _textblock; public TextBlock _warningBlock; public ProgressBar _loading; // Avalonia has no ProgressRing; use indeterminate ProgressBar + private readonly TextBlock _stateLabel; + private static readonly string EnabledLabel = CoreTools.Translate("Enabled"); + private static readonly string DisabledLabel = CoreTools.Translate("Disabled"); private bool IS_INVERTED; private SecureSettings.K setting_name = SecureSettings.K.Unset; @@ -37,6 +40,7 @@ public SecureSettings.K SettingName IS_INVERTED = SecureSettings.ResolveKey(value).StartsWith("Disable"); _checkbox.IsChecked = SecureSettings.Get(setting_name) ^ IS_INVERTED ^ ForceInversion; _textblock.Opacity = (_checkbox.IsChecked ?? false) ? 1 : 0.7; + UpdateStateLabel(); _checkbox.IsEnabled = true; } } @@ -77,9 +81,17 @@ public SecureCheckboxCard() { _checkbox = new ToggleSwitch { + // OnContent/OffContent intentionally left null — the state label is + // a sibling TextBlock placed to the LEFT of the knob below. + OnContent = null, + OffContent = null, + VerticalAlignment = VerticalAlignment.Center, + }; + _stateLabel = new TextBlock + { + Text = DisabledLabel, + VerticalAlignment = VerticalAlignment.Center, Margin = new Thickness(0, 0, 8, 0), - OnContent = new TextBlock { Text = CoreTools.Translate("Enabled") }, - OffContent = new TextBlock { Text = CoreTools.Translate("Disabled") }, }; _loading = new ProgressBar { @@ -108,7 +120,8 @@ public SecureCheckboxCard() { Spacing = 4, Orientation = Orientation.Horizontal, - Children = { _loading, _checkbox }, + VerticalAlignment = VerticalAlignment.Center, + Children = { _loading, _stateLabel, _checkbox }, }; Header = new StackPanel { @@ -150,6 +163,7 @@ await SecureSettings.TrySet( cmd.Execute(null); _textblock.Opacity = (_checkbox.IsChecked ?? false) ? 1 : 0.7; _checkbox.IsChecked = SecureSettings.Get(setting_name) ^ IS_INVERTED ^ ForceInversion; + UpdateStateLabel(); if (_textblock.Text is not null) { AccessibilityAnnouncementService.AnnounceToggle(_textblock.Text, _checkbox.IsChecked ?? false); @@ -161,8 +175,14 @@ await SecureSettings.TrySet( { Logger.Warn(ex); _checkbox.IsChecked = SecureSettings.Get(setting_name) ^ IS_INVERTED ^ ForceInversion; + UpdateStateLabel(); _loading.IsVisible = false; _checkbox.IsEnabled = true; } } + + private void UpdateStateLabel() + { + _stateLabel.Text = (_checkbox.IsChecked ?? false) ? EnabledLabel : DisabledLabel; + } } diff --git a/src/UniGetUI.Avalonia/Views/MainWindow.axaml b/src/UniGetUI.Avalonia/Views/MainWindow.axaml index c9c8d0d9d..4044c15d8 100644 --- a/src/UniGetUI.Avalonia/Views/MainWindow.axaml +++ b/src/UniGetUI.Avalonia/Views/MainWindow.axaml @@ -310,7 +310,8 @@ VerticalAlignment="Center" Orientation="Horizontal" Margin="65,0,8,0" - Spacing="8"> + Spacing="8" + Opacity="0.6"> - @@ -334,7 +335,8 @@ VerticalAlignment="Center" automation:AutomationProperties.AccessibilityView="Control" Orientation="Horizontal" - Spacing="0"> + Spacing="0" + Opacity="0.6"> - - + @@ -209,7 +219,8 @@ Padding="2" Background="Transparent" BorderThickness="0"> - + - + VerticalAlignment="Center"> + + + + + + + + + + + + + + + + IsVisible="{Binding IsExpanded}" + Margin="24,0,0,0"> + GridLinesVisibility="None"> @@ -693,7 +740,10 @@ - + @@ -703,7 +753,7 @@ VerticalAlignment="Center">