Browse Source

Implement PropertyGrid multiple vm editing

pull/333/head
Ionite 12 months ago
parent
commit
9dac1c4850
No known key found for this signature in database
  1. 55
      StabilityMatrix.Avalonia/Controls/PropertyGrid/BetterPropertyGrid.cs
  2. 100
      StabilityMatrix.Avalonia/Controls/StackExpander.axaml
  3. 17
      StabilityMatrix.Avalonia/DesignData/DesignData.cs
  4. 10
      StabilityMatrix.Avalonia/DesignData/MockPropertyGridObject.cs
  5. 10
      StabilityMatrix.Avalonia/ViewModels/Dialogs/PropertyGridViewModel.cs
  6. 49
      StabilityMatrix.Avalonia/Views/Dialogs/PropertyGridDialog.axaml
  7. 43
      StabilityMatrix.Avalonia/Views/Dialogs/PropertyGridDialog.axaml.cs

55
StabilityMatrix.Avalonia/Controls/PropertyGrid/BetterPropertyGrid.cs

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Avalonia;
using Avalonia.PropertyGrid.Services;
using JetBrains.Annotations;
using PropertyModels.ComponentModel;
@ -14,10 +15,56 @@ public class BetterPropertyGrid : global::Avalonia.PropertyGrid.Controls.Propert
{
protected override Type StyleKeyOverride => typeof(global::Avalonia.PropertyGrid.Controls.PropertyGrid);
public static readonly StyledProperty<IEnumerable<string>> ExcludedCategoriesProperty = AvaloniaProperty.Register<
BetterPropertyGrid,
IEnumerable<string>
>("ExcludedCategories");
public IEnumerable<string> ExcludedCategories
{
get => GetValue(ExcludedCategoriesProperty);
set => SetValue(ExcludedCategoriesProperty, value);
}
public static readonly StyledProperty<IEnumerable<string>> IncludedCategoriesProperty = AvaloniaProperty.Register<
BetterPropertyGrid,
IEnumerable<string>
>("IncludedCategories");
public IEnumerable<string> IncludedCategories
{
get => GetValue(IncludedCategoriesProperty);
set => SetValue(IncludedCategoriesProperty, value);
}
static BetterPropertyGrid()
{
// Initialize localization and name resolver
LocalizationService.Default.AddExtraService(new PropertyGridLocalizationService());
ExcludedCategoriesProperty
.Changed
.AddClassHandler<BetterPropertyGrid>(
(grid, args) =>
{
if (args.NewValue is IEnumerable<string> excludedCategories)
{
grid.FilterExcludeCategories(excludedCategories);
}
}
);
IncludedCategoriesProperty
.Changed
.AddClassHandler<BetterPropertyGrid>(
(grid, args) =>
{
if (args.NewValue is IEnumerable<string> includedCategories)
{
grid.FilterIncludeCategories(includedCategories);
}
}
);
}
public void FilterExcludeCategories(IEnumerable<string> excludedCategories)
@ -55,9 +102,13 @@ public class BetterPropertyGrid : global::Avalonia.PropertyGrid.Controls.Propert
categoryFilter.BeginUpdate();
// Uncheck All and check Misc by default
// Uncheck non-included categories
foreach (var mask in categoryFilter.Masks.Where(m => !includeCategories.Contains(m)))
{
categoryFilter.UnCheck(mask);
}
categoryFilter.UnCheck(categoryFilter.All);
categoryFilter.Check("Misc");
// Check included categories
foreach (var mask in includeCategories)

100
StabilityMatrix.Avalonia/Controls/StackExpander.axaml

@ -1,85 +1,97 @@
<Styles xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:StabilityMatrix.Avalonia.Controls"
xmlns:mocks="clr-namespace:StabilityMatrix.Avalonia.DesignData"
xmlns:vmInference="clr-namespace:StabilityMatrix.Avalonia.ViewModels.Inference"
xmlns:local="clr-namespace:StabilityMatrix.Avalonia"
xmlns:fluentIcons="clr-namespace:FluentIcons.FluentAvalonia;assembly=FluentIcons.FluentAvalonia"
x:DataType="vmInference:StackExpanderViewModel">
<Styles
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:StabilityMatrix.Avalonia.Controls"
xmlns:fluentIcons="clr-namespace:FluentIcons.FluentAvalonia;assembly=FluentIcons.FluentAvalonia"
xmlns:local="clr-namespace:StabilityMatrix.Avalonia"
xmlns:mocks="clr-namespace:StabilityMatrix.Avalonia.DesignData"
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
xmlns:vmInference="clr-namespace:StabilityMatrix.Avalonia.ViewModels.Inference"
x:DataType="vmInference:StackExpanderViewModel">
<Design.PreviewWith>
<Grid Width="500" Height="800">
<StackPanel>
<controls:StackExpander
DataContext="{x:Static mocks:DesignData.StackExpanderViewModel}"/>
<controls:StackExpander DataContext="{x:Static mocks:DesignData.StackExpanderViewModel}" />
<controls:StackExpander DataContext="{x:Static mocks:DesignData.StackExpanderViewModel2}" />
</StackPanel>
</Grid>
</Design.PreviewWith>
<Style Selector="controls|StackExpander">
<!-- Set Defaults -->
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<!-- Set Defaults -->
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="Template">
<ControlTemplate>
<Expander
VerticalContentAlignment="Top"
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
VerticalAlignment="{TemplateBinding VerticalAlignment}"
HorizontalContentAlignment="Stretch"
VerticalAlignment="{TemplateBinding VerticalAlignment}">
VerticalContentAlignment="Top">
<Expander.Styles>
<Style Selector="Expander /template/ ToggleButton#PART_toggle">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</Expander.Styles>
<Expander.Header>
<Grid ColumnDefinitions="Auto,Auto,*,Auto">
<ToggleSwitch
Margin="2,0,0,2"
IsChecked="{Binding IsEnabled}"
VerticalContentAlignment="Center"
OnContent=""
OffContent=""/>
IsChecked="{Binding IsEnabled}"
OffContent=""
OnContent="" />
<TextBlock
Grid.Column="1"
VerticalAlignment="Center"
Text="{Binding TitleExtra}"
IsVisible="{Binding TitleExtra, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
<TextBlock
IsVisible="{Binding TitleExtra, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
Text="{Binding TitleExtra}" />
<TextBlock
Grid.Column="2"
VerticalAlignment="Center"
Text="{Binding Title}"/>
<Button
IsVisible="{Binding IsEditEnabled}"
Command="{Binding RemoveFromParentListCommand}"
Text="{Binding Title}" />
<!-- Delete button for StackEditableCard -->
<Button
Grid.Column="3"
Padding="12,6"
HorizontalAlignment="Right"
Classes="transparent-red"
Grid.Column="3"
Padding="10,4"
HorizontalAlignment="Right">
<fluentIcons:SymbolIcon Symbol="Delete" FontSize="16" />
Command="{Binding RemoveFromParentListCommand}"
IsVisible="{Binding IsEditEnabled}">
<fluentIcons:SymbolIcon FontSize="16" Symbol="Delete" />
</Button>
<!-- Settings button -->
<Button
Grid.Column="3"
Padding="12,6"
HorizontalAlignment="Right"
Classes="transparent-full"
Command="{Binding SettingsCommand}"
IsVisible="{Binding IsSettingsEnabled}">
<fluentIcons:SymbolIcon FontSize="17" Symbol="Settings" />
</Button>
</Grid>
</Expander.Header>
<Panel>
<ItemsControl
VerticalAlignment="Top"
ItemsSource="{Binding Cards}">
<ItemsControl VerticalAlignment="Top" ItemsSource="{Binding Cards}">
<ItemsControl.Styles>
<Style Selector="controls|Card">
<Setter Property="IsCardVisualsEnabled" Value="False"/>
<Setter Property="IsCardVisualsEnabled" Value="False" />
</Style>
</ItemsControl.Styles>
<ItemsControl.DataTemplates>
<local:ViewLocator/>
<local:ViewLocator />
</ItemsControl.DataTemplates>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel
<StackPanel
x:Name="PART_ItemsPanel"
VerticalAlignment="Top"
Spacing="{TemplateBinding Spacing}" />
@ -88,7 +100,7 @@
</ItemsControl>
</Panel>
</Expander>
</ControlTemplate>
</Setter>

17
StabilityMatrix.Avalonia/DesignData/DesignData.cs

@ -1,11 +1,13 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Net.Http;
using System.Text;
using AvaloniaEdit.Utils;
using CommunityToolkit.Mvvm.ComponentModel;
using DynamicData;
using DynamicData.Binding;
using Microsoft.Extensions.DependencyInjection;
@ -631,7 +633,11 @@ The gallery images are often inpainted, but you will get something very similar
public static PropertyGridViewModel PropertyGridViewModel =>
DialogFactory.Get<PropertyGridViewModel>(vm =>
{
vm.SelectedObject = new MockPropertyGridObject();
vm.SelectedObject = new INotifyPropertyChanged[]
{
new MockPropertyGridObject(),
new MockPropertyGridObjectAlt()
};
vm.ExcludeCategories = ["Excluded Category"];
});
@ -732,6 +738,15 @@ The gallery images are often inpainted, but you will get something very similar
vm.OnContainerIndexChanged(0);
});
public static StackExpanderViewModel StackExpanderViewModel2 =>
DialogFactory.Get<StackExpanderViewModel>(vm =>
{
vm.Title = "Hires Fix";
vm.IsSettingsEnabled = true;
vm.AddCards(UpscalerCardViewModel, SamplerCardViewModel);
vm.OnContainerIndexChanged(1);
});
public static UpscalerCardViewModel UpscalerCardViewModel => DialogFactory.Get<UpscalerCardViewModel>();
public static BatchSizeCardViewModel BatchSizeCardViewModel => DialogFactory.Get<BatchSizeCardViewModel>();

10
StabilityMatrix.Avalonia/DesignData/MockPropertyGridObject.cs

@ -42,3 +42,13 @@ public partial class MockPropertyGridObject : ObservableObject
[property: Category("Excluded Category")]
private string? stringExcludedCategoryProperty;
}
public partial class MockPropertyGridObjectAlt : ObservableObject
{
[ObservableProperty]
private int altIntProperty = 10;
[ObservableProperty]
[property: Category("Settings")]
private string? altStringProperty;
}

10
StabilityMatrix.Avalonia/ViewModels/Dialogs/PropertyGridViewModel.cs

@ -1,8 +1,11 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using Avalonia.PropertyGrid.ViewModels;
using CommunityToolkit.Mvvm.ComponentModel;
using OneOf;
using StabilityMatrix.Avalonia.DesignData;
using StabilityMatrix.Avalonia.ViewModels.Base;
using StabilityMatrix.Avalonia.Views.Dialogs;
using StabilityMatrix.Core.Attributes;
@ -15,10 +18,11 @@ namespace StabilityMatrix.Avalonia.ViewModels.Dialogs;
public partial class PropertyGridViewModel : TaskDialogViewModelBase
{
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(SelectedObjectSource))]
[NotifyPropertyChangedFor(nameof(SelectedObjectItemsSource))]
private OneOf<INotifyPropertyChanged, IEnumerable<INotifyPropertyChanged>>? selectedObject;
public object? SelectedObjectSource => SelectedObject?.Value;
public IEnumerable<INotifyPropertyChanged>? SelectedObjectItemsSource =>
SelectedObject?.Match(single => [single], multiple => multiple);
[ObservableProperty]
private PropertyGridShowStyle showStyle = PropertyGridShowStyle.Alphabetic;

49
StabilityMatrix.Avalonia/Views/Dialogs/PropertyGridDialog.axaml

@ -1,22 +1,33 @@
<controls:UserControlBase xmlns="https://github.com/avaloniaui"
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:mocks="clr-namespace:StabilityMatrix.Avalonia.DesignData"
xmlns:controls="clr-namespace:StabilityMatrix.Avalonia.Controls"
xmlns:vmDialogs="clr-namespace:StabilityMatrix.Avalonia.ViewModels.Dialogs"
xmlns:pg="clr-namespace:Avalonia.PropertyGrid.Controls;assembly=Avalonia.PropertyGrid"
d:DataContext="{x:Static mocks:DesignData.PropertyGridViewModel}"
x:DataType="vmDialogs:PropertyGridViewModel"
mc:Ignorable="d" d:DesignWidth="600" d:DesignHeight="450"
x:Class="StabilityMatrix.Avalonia.Views.Dialogs.PropertyGridDialog">
<controls:UserControlBase
x:Class="StabilityMatrix.Avalonia.Views.Dialogs.PropertyGridDialog"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:componentModel="clr-namespace:System.ComponentModel;assembly=System.ObjectModel"
xmlns:controls="clr-namespace:StabilityMatrix.Avalonia.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mocks="clr-namespace:StabilityMatrix.Avalonia.DesignData"
xmlns:vmDialogs="clr-namespace:StabilityMatrix.Avalonia.ViewModels.Dialogs"
d:DataContext="{x:Static mocks:DesignData.PropertyGridViewModel}"
d:DesignHeight="450"
d:DesignWidth="600"
x:DataType="vmDialogs:PropertyGridViewModel"
mc:Ignorable="d">
<Grid>
<controls:BetterPropertyGrid
x:Name="MainPropertyGrid"
SelectedObject="{Binding SelectedObjectSource, Mode=OneTime}"
ShowStyle="{Binding ShowStyle}"
AllowQuickFilter="False"
AllowFilter="False"
ShowTitle="False" />
<ItemsControl x:Name="MainItemsControl" ItemsSource="{Binding SelectedObjectItemsSource, Mode=OneTime}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="componentModel:INotifyPropertyChanged">
<controls:BetterPropertyGrid
AllowFilter="False"
AllowQuickFilter="False"
SelectedObject="{Binding Mode=OneTime}"
IncludedCategories="{Binding $parent[ItemsControl].((vmDialogs:PropertyGridViewModel)DataContext).IncludeCategories, Mode=OneTime, FallbackValue=''}"
ExcludedCategories="{Binding $parent[ItemsControl].((vmDialogs:PropertyGridViewModel)DataContext).ExcludeCategories, Mode=OneTime, FallbackValue=''}"
ShowStyle="{Binding $parent[ItemsControl].((vmDialogs:PropertyGridViewModel)DataContext).ShowStyle, Mode=OneTime, FallbackValue=Alphabetic}"
ShowTitle="False" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</controls:UserControlBase>

43
StabilityMatrix.Avalonia/Views/Dialogs/PropertyGridDialog.axaml.cs

@ -1,9 +1,4 @@
using Avalonia.Controls.Primitives;
using Avalonia.PropertyGrid.Controls;
using Avalonia.PropertyGrid.ViewModels;
using PropertyModels.ComponentModel;
using StabilityMatrix.Avalonia.Controls;
using StabilityMatrix.Avalonia.ViewModels.Dialogs;
using StabilityMatrix.Avalonia.Controls;
using StabilityMatrix.Core.Attributes;
namespace StabilityMatrix.Avalonia.Views.Dialogs;
@ -15,40 +10,4 @@ public partial class PropertyGridDialog : UserControlBase
{
InitializeComponent();
}
/// <inheritdoc />
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
base.OnApplyTemplate(e);
var vm = DataContext as PropertyGridViewModel;
if (vm?.ExcludeCategories is { } excludeCategories)
{
MainPropertyGrid.FilterExcludeCategories(excludeCategories);
}
if (vm?.IncludeCategories is { } includeCategories)
{
MainPropertyGrid.FilterIncludeCategories(includeCategories);
}
}
internal class CustomFilter : IPropertyGridFilterContext
{
/// <inheritdoc />
public IFilterPattern? FilterPattern => null;
/// <inheritdoc />
public ICheckedMaskModel? FastFilterPattern => null;
/// <inheritdoc />
public PropertyVisibility PropagateVisibility(
IPropertyGridCellInfo info,
FilterCategory category = FilterCategory.Default
)
{
return PropertyVisibility.AlwaysVisible;
}
}
}

Loading…
Cancel
Save