Почти закончил с WPF

This commit is contained in:
2025-05-20 17:20:37 +04:00
parent 03a644624f
commit 0274d9cbef
31 changed files with 786 additions and 601 deletions
+3 -4
View File
@@ -6,6 +6,7 @@ using Pf2eDataScrapper.App;
using Pf2eDataScrapper.Helpers;
using Pf2eDataScrapper.Processors;
using Pf2eDataScrapper.WPF;
using Pf2eDataScrapper.WPF.EntityViewer;
using Pf2eDataScrapper.WPF.Views;
using Pf2eModel;
using Slugify;
@@ -53,7 +54,7 @@ internal sealed class ImportApplication : Application
private StartForm? _startFormWpf;
private ProgressFormWpf? _progressFormWpf;
private ProgressForm? _progressFormWpf;
private EntityForm? _entityForm;
@@ -89,9 +90,7 @@ internal sealed class ImportApplication : Application
ServiceProvider
);
_progressFormWpf = ActivatorUtilities.CreateInstance<ProgressFormWpf>(
ServiceProvider
);
_progressFormWpf = ActivatorUtilities.CreateInstance<ProgressForm>(ServiceProvider);
_progressFormWpf.WindowStartupLocation = WindowStartupLocation.CenterScreen;
_progressFormWpf.Closing += Wpf_HandleFormClosing;
_progressFormWpf.ApplicationStateChange += ApplicationStateChange;
@@ -1,99 +0,0 @@
<UserControl
x:Class="Pf2eDataScrapper.WPF.Components.EntityViewControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:conv="clr-namespace:Pf2eDataScrapper.WPF.ViewModels.EntityViewStructure"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Pf2eDataScrapper.WPF.Components"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewModels="clr-namespace:Pf2eDataScrapper.WPF.ViewModels"
d:DataContext="{d:DesignInstance Type=viewModels:EntityViewViewModel}"
d:DesignHeight="450"
d:DesignWidth="300"
x:ClassModifier="internal"
mc:Ignorable="d">
<UserControl.BorderBrush>
<SolidColorBrush Color="{DynamicResource {x:Static SystemColors.ActiveBorderColorKey}}" />
</UserControl.BorderBrush>
<UserControl.Background>
<SolidColorBrush Color="{DynamicResource {x:Static SystemColors.ControlColorKey}}" />
</UserControl.Background>
<UserControl.Resources>
<conv:LadderToImageConverter x:Key="LadderToImageConverter" />
<Style TargetType="{x:Type DockPanel}">
<Setter Property="Background" Value="{x:Static SystemColors.ControlBrush}" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{x:Static SystemColors.ControlLightBrush}" />
</Trigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
<ScrollViewer>
<ItemsControl ItemsSource="{Binding Rows}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<DockPanel Style="{StaticResource {x:Type DockPanel}}">
<DockPanel.Height>
<Binding Path="ItemHeight" RelativeSource="{RelativeSource AncestorType=local:EntityViewControl}" />
</DockPanel.Height>
<StackPanel Width="200" Orientation="Horizontal">
<Image Margin="0,0,2,0">
<Image.Source>
<MultiBinding Converter="{StaticResource LadderToImageConverter}">
<Binding Path="Ladder" />
<Binding Path="ItemHeight" RelativeSource="{RelativeSource AncestorType=local:EntityViewControl}" />
</MultiBinding>
</Image.Source>
</Image>
<Button
Width="15"
Height="15"
Margin="-24,0,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
BorderThickness="1"
Visibility="{Binding ButtonVisibility}">
<Button.Resources>
<Style TargetType="Border">
<Setter Property="CornerRadius" Value="3" />
</Style>
</Button.Resources>
<!--<Button.Width>
<Binding Path="ButtonSize" RelativeSource="{RelativeSource AncestorType=local:EntityViewControl}" />
</Button.Width>
<Button.Height>
<Binding Path="ButtonSize" RelativeSource="{RelativeSource AncestorType=local:EntityViewControl}" />
</Button.Height>-->
+
</Button>
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
Text="{Binding Name}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock
Margin="0,0,5,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="{Binding TypeFontSize, RelativeSource={RelativeSource AncestorType=local:EntityViewControl}}"
FontStyle="Italic"
Text="{Binding Type}" />
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
Text="{Binding Value}" />
</StackPanel>
</DockPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</UserControl>
@@ -1,13 +1,13 @@
<UserControl
x:Class="Pf2eDataScrapper.WPF.Components.DbEntityListControl"
x:Class="Pf2eDataScrapper.WPF.EntityViewer.Component.EntityListControl"
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:local="clr-namespace:Pf2eDataScrapper.WPF.Components"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewModels="clr-namespace:Pf2eDataScrapper.WPF.ViewModels"
xmlns:viewmodel="clr-namespace:Pf2eDataScrapper.WPF.EntityViewer.ViewModel"
Padding="3,3,3,3"
d:DataContext="{d:DesignInstance Type=viewModels:DbEntityListViewModel}"
d:DataContext="{d:DesignInstance Type=viewmodel:EntityListViewModel}"
d:DesignHeight="450"
d:DesignWidth="400"
x:ClassModifier="internal"
@@ -1,14 +1,14 @@
using System.Windows;
using Pf2eDataScrapper.WPF.ViewModels;
using Pf2eDataScrapper.WPF.EntityViewer.ViewModel;
namespace Pf2eDataScrapper.WPF.Components;
namespace Pf2eDataScrapper.WPF.EntityViewer.Component;
/// <summary>
/// Логика взаимодействия для DbEntityListControl.xaml
/// </summary>
internal partial class DbEntityListControl : System.Windows.Controls.UserControl
internal partial class EntityListControl : System.Windows.Controls.UserControl
{
public DbEntityListViewModel? ViewModel
public EntityListViewModel? ViewModel
{
get => _viewModel;
set
@@ -18,9 +18,9 @@ internal partial class DbEntityListControl : System.Windows.Controls.UserControl
}
}
private DbEntityListViewModel? _viewModel;
private EntityListViewModel? _viewModel;
public DbEntityListControl()
public EntityListControl()
{
InitializeComponent();
}
@@ -0,0 +1,123 @@
<UserControl
x:Class="Pf2eDataScrapper.WPF.EntityViewer.Component.ViewControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:component="clr-namespace:Pf2eDataScrapper.WPF.EntityViewer.Component"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:fa="http://schemas.awesome.incremented/wpf/xaml/fontawesome.sharp"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewmodel="clr-namespace:Pf2eDataScrapper.WPF.EntityViewer.ViewModel"
x:Name="_this"
d:DataContext="{d:DesignInstance Type=viewmodel:ViewViewModel}"
d:DesignHeight="450"
d:DesignWidth="300"
x:ClassModifier="internal"
mc:Ignorable="d">
<UserControl.Resources>
<FontFamily x:Key="FontAwesome">/FontAwesome.Sharp;component/fonts/#Font Awesome 6 Free Solid</FontFamily>
<Style x:Key="ButtonStyle" TargetType="Button">
<Setter Property="FontSize" Value="{Binding ButtonSize, ElementName=_this}" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="Margin" Value="0" />
<Setter Property="Padding" Value="0" />
<Setter Property="Width" Value="{Binding ButtonSize, ElementName=_this}" />
<Setter Property="Height" Value="{Binding ButtonSize, ElementName=_this}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Background">
<Setter.Value>
<SolidColorBrush Color="{DynamicResource {x:Static SystemColors.ControlColorKey}}" />
</Setter.Value>
</Setter>
<Setter Property="BorderBrush">
<Setter.Value>
<SolidColorBrush Color="{DynamicResource {x:Static SystemColors.ControlColorKey}}" />
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="Black" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="DarkGray" />
</Trigger>
</Style.Triggers>
</Style>
<Style
x:Key="FaButtonStyle"
BasedOn="{StaticResource ButtonStyle}"
TargetType="Button">
<Setter Property="FontFamily" Value="{StaticResource FontAwesome}" />
</Style>
</UserControl.Resources>
<UserControl.BorderBrush>
<SolidColorBrush Color="{DynamicResource {x:Static SystemColors.ActiveBorderColorKey}}" />
</UserControl.BorderBrush>
<UserControl.Background>
<SolidColorBrush Color="{DynamicResource {x:Static SystemColors.ControlColorKey}}" />
</UserControl.Background>
<ScrollViewer>
<ItemsControl ItemsSource="{Binding Rows}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Grid.IsSharedSizeScope="True" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Height="{Binding ItemHeight, ElementName=_this}" Visibility="{Binding ItemVisibility}">
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="ColumnOne" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Orientation="Horizontal">
<component:ViewLadder
Width="65"
Height="{Binding ItemHeight, ElementName=_this}"
DepthSize="{Binding DepthSize, ElementName=_this}"
Ladder="{Binding Ladder}" />
<Button
Margin="-22,0,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Command="{Binding CollapseCommand}"
Content="{Binding ButtonIcon}"
Style="{StaticResource FaButtonStyle}"
Visibility="{Binding ButtonVisibility}" />
<TextBlock
Margin="2,0,10,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Text="{Binding Name}" />
</StackPanel>
<StackPanel Grid.Column="1" Orientation="Horizontal">
<TextBlock
Margin="0,0,5,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="{Binding TypeFontSize, ElementName=_this}"
FontStyle="Italic"
Text="{Binding Type}" />
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
Text="{Binding Value}" />
</StackPanel>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</UserControl>
@@ -14,26 +14,11 @@ using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Pf2eDataScrapper.Helpers;
using Pf2eDataScrapper.WPF.ViewModels;
using Pf2eDataScrapper.WPF.ViewModels.EntityViewStructure;
using Color = System.Windows.Media.Color;
using SystemColors = System.Windows.SystemColors;
namespace Pf2eDataScrapper.WPF.Components;
namespace Pf2eDataScrapper.WPF.EntityViewer.Component;
internal partial class EntityViewControl : System.Windows.Controls.UserControl
internal partial class ViewControl : UserControl
{
public EntityViewViewModel? ViewModel
{
get => _viewModel;
set
{
_viewModel = value;
DataContext = ViewModel;
}
}
private EntityViewViewModel? _viewModel;
#region "Поля элемента управления"
/// <summary>
@@ -42,16 +27,17 @@ internal partial class EntityViewControl : System.Windows.Controls.UserControl
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[Category("Entity Render")]
[Description("The height of each item in the tree view.")]
public int ItemHeight
public double ItemHeight
{
get => _itemHeight;
set
{
_itemHeight = value;
Resources["ItemHeight"] = ItemHeight;
get { return (double)GetValue(ItemHeightProperty); }
set { SetValue(ItemHeightProperty, value); }
}
}
private int _itemHeight = 20;
public static readonly DependencyProperty ItemHeightProperty = DependencyProperty.Register(
"ItemHeight",
typeof(double),
typeof(ViewControl),
new PropertyMetadata(20.0)
);
/// <summary>
/// Ширина отступа глубины.
@@ -59,7 +45,17 @@ internal partial class EntityViewControl : System.Windows.Controls.UserControl
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[Category("Entity Render")]
[Description("The size of tab.")]
public int DepthSize { get; set; } = 20;
public double DepthSize
{
get { return (double)GetValue(DepthSizeProperty); }
set { SetValue(DepthSizeProperty, value); }
}
public static readonly DependencyProperty DepthSizeProperty = DependencyProperty.Register(
"DepthSize",
typeof(double),
typeof(ViewControl),
new PropertyMetadata(20.0)
);
/// <summary>
/// Размер шрифта типа поля сущности.
@@ -67,7 +63,17 @@ internal partial class EntityViewControl : System.Windows.Controls.UserControl
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[Category("Entity Render")]
[Description("The size of tab.")]
public float TypeFontSize { get; set; } = 9.5f;
public double TypeFontSize
{
get { return (double)GetValue(TypeFontSizeProperty); }
set { SetValue(TypeFontSizeProperty, value); }
}
public static readonly DependencyProperty TypeFontSizeProperty = DependencyProperty.Register(
"TypeFontSize",
typeof(double),
typeof(ViewControl),
new PropertyMetadata(9.5)
);
/// <summary>
/// Размер кнопки плюс/минус.
@@ -75,23 +81,22 @@ internal partial class EntityViewControl : System.Windows.Controls.UserControl
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[Category("Entity Render")]
[Description("The size of plus/minus button.")]
public int ButtonSize { get; set; } = 20;
/// <summary>
/// Ширина имени поля сущности.
/// </summary>
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public int NameWidth { get; private set; } = 200;
public double ButtonSize
{
get { return (double)GetValue(ButtonSizeProperty); }
set { SetValue(ButtonSizeProperty, value); }
}
public static readonly DependencyProperty ButtonSizeProperty = DependencyProperty.Register(
"ButtonSize",
typeof(double),
typeof(ViewControl),
new PropertyMetadata(12.0)
);
#endregion
public EntityViewControl()
public ViewControl()
{
InitializeComponent();
Resources["ItemHeight"] = ItemHeight;
}
}
@@ -0,0 +1,13 @@
<UserControl
x:Class="Pf2eDataScrapper.WPF.EntityViewer.Component.ViewLadder"
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:local="clr-namespace:Pf2eDataScrapper.WPF.EntityViewer.Component"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="20"
d:DesignWidth="60"
x:ClassModifier="internal"
mc:Ignorable="d">
<Canvas x:Name="TargetCanvas" />
</UserControl>
@@ -0,0 +1,140 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Pf2eDataScrapper.WPF.EntityViewer;
using Pf2eDataScrapper.WPF.EntityViewer.EntityViewStructure;
namespace Pf2eDataScrapper.WPF.EntityViewer.Component;
/// <summary>
/// Логика взаимодействия для ViewLadder.xaml
/// </summary>
internal partial class ViewLadder : UserControl
{
/// <summary>
/// Ширина отступа глубины.
/// </summary>
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[Category("Entity Render")]
[Description("The size of tab.")]
public double DepthSize
{
get { return (double)GetValue(DepthSizeProperty); }
set { SetValue(DepthSizeProperty, value); }
}
public static readonly DependencyProperty DepthSizeProperty = DependencyProperty.Register(
"DepthSize",
typeof(double),
typeof(ViewLadder),
new FrameworkPropertyMetadata(20.0, new PropertyChangedCallback(OnValueChanged))
);
public IEnumerable<LadderType> Ladder
{
get { return (IEnumerable<LadderType>)GetValue(LadderProperty); }
set
{
SetValue(LadderProperty, value);
}
}
public static readonly DependencyProperty LadderProperty = DependencyProperty.Register(
"Ladder",
typeof(IEnumerable<LadderType>),
typeof(ViewLadder),
new FrameworkPropertyMetadata(Array.Empty<LadderType>(), new PropertyChangedCallback(OnValueChanged))
);
private static void OnValueChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
{
ViewLadder control = (ViewLadder)obj;
control.Rebuild();
}
public ViewLadder()
{
InitializeComponent();
}
public void Rebuild()
{
int n = Ladder.Count();
Width = n * DepthSize;
DrawingGroup result = new();
result.Children.Add(
new GeometryDrawing()
{
Geometry = new RectangleGeometry(new(0, 0, n * DepthSize, Height)),
Pen = new(Brushes.Transparent, 0),
}
);
result.Children.Add(
new GeometryDrawing()
{
Geometry = GetLadderGeometryGroup(Ladder, DepthSize, Height),
Pen = new(Brushes.Black, 1),
}
);
TargetCanvas.Background = new DrawingBrush(result);
}
private GeometryGroup GetLadderGeometryGroup(IEnumerable<LadderType> ladder, double w, double h)
{
GeometryGroup geometryGroup = new();
double w2 = w / 2;
double h2 = h / 2;
int i = 0;
foreach (LadderType ladderType in ladder)
{
switch (ladderType)
{
case LadderType.Empty:
break;
case LadderType.Last:
geometryGroup.Children.Add(
new LineGeometry(new(i * w + w2, 0), new(i * w + w2, h2))
);
geometryGroup.Children.Add(
new LineGeometry(new(i * w + w2, h2), new(i * w + w, h2))
);
break;
case LadderType.Through:
geometryGroup.Children.Add(
new LineGeometry(new(i * w + w2, 0), new(i * w + w2, h))
);
if (i == ladder.Count() - 1)
{
geometryGroup.Children.Add(
new LineGeometry(new(i * w + w2, h2), new(i * w + w, h2))
);
}
break;
default:
throw new ArgumentOutOfRangeException(nameof(ladder));
}
i++;
}
return geometryGroup;
}
}
@@ -1,16 +1,13 @@
<Window
x:Class="Pf2eDataScrapper.WPF.Views.EntityForm"
x:Class="Pf2eDataScrapper.WPF.EntityViewer.EntityForm"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:components="clr-namespace:Pf2eDataScrapper.WPF.Components"
xmlns:component="clr-namespace:Pf2eDataScrapper.WPF.EntityViewer.Component"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Pf2eDataScrapper.WPF"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewModels="clr-namespace:Pf2eDataScrapper.WPF.ViewModels"
Title="EntityForm"
Width="1400"
Height="800"
d:DataContext="{d:DesignInstance Type=viewModels:EntityFormViewModel}"
x:ClassModifier="internal"
Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"
Loaded="Window_Loaded"
@@ -59,15 +56,15 @@
ItemsSource="{Binding EntityTypes}"
SelectedItem="{Binding SelectedEntityType}" />
<components:DbEntityListControl
x:Name="DbEntityListControl"
<component:EntityListControl
x:Name="EntityListControl"
Grid.Row="2"
Grid.RowSpan="2"
Grid.Column="0"
ClipToBounds="True" />
<components:EntityViewControl
x:Name="EntityViewControl"
<component:ViewControl
x:Name="ViewControl"
Grid.Row="0"
Grid.RowSpan="4"
Grid.Column="2"
@@ -1,15 +1,12 @@
using System.Collections.ObjectModel;
using System.Windows;
using Pf2eDataScrapper.WPF.Components;
using Pf2eDataScrapper.WPF.ViewModels;
using Pf2eDataScrapper.WPF.EntityViewer.ViewModel;
using Pf2eModel;
using Pf2eModel.Model.Enum;
namespace Pf2eDataScrapper.WPF.Views;
namespace Pf2eDataScrapper.WPF.EntityViewer;
/// <summary>
/// Логика взаимодействия для EntityForm.xaml
/// </summary>
internal partial class EntityForm : Window
{
public Pf2eDbContext Context { get; }
@@ -18,20 +15,19 @@ internal partial class EntityForm : Window
public EntityForm(
Pf2eDbContext context,
EntityFormViewModel viewModel,
DbEntityListViewModel dbEntityListViewModel,
EntityViewViewModel entityViewViewModel
ViewViewModel entityViewViewModel
)
{
Context = context;
ViewModel = viewModel;
InitializeComponent();
DbEntityListControl.ViewModel = dbEntityListViewModel;
EntityViewControl.ViewModel = entityViewViewModel;
EntityListControl.DataContext = ViewModel.DbEntityListViewModel;
ViewControl.DataContext = ViewModel.ViewViewModel;
DataContext = ViewModel;
dbEntityListViewModel.Reload();
ViewModel.DbEntityListViewModel.Reload();
}
private void Window_Loaded(object sender, RoutedEventArgs e) { }
@@ -1,4 +1,4 @@
namespace Pf2eDataScrapper.WPF.ViewModels.EntityViewStructure;
namespace Pf2eDataScrapper.WPF.EntityViewer.EntityViewStructure;
/// <summary>
/// Тип лестницы глубины.
@@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Linq;
namespace Pf2eDataScrapper.WPF.ViewModels.EntityViewStructure;
namespace Pf2eDataScrapper.WPF.EntityViewer.EntityViewStructure;
/// <summary>
/// Класс для построения структуры данных класса.
@@ -0,0 +1,218 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
namespace Pf2eDataScrapper.WPF.EntityViewer.EntityViewStructure;
/// <summary>
/// Базовый класс для полей структуры.
/// </summary>
/// <param name="builder">Класс построения структуры данных.</param>
/// <param name="name">Название поля.</param>
/// <param name="depth">Глубина поля.</param>
internal abstract class StructureField(StructureBuilder builder, string name, int depth) : INotifyPropertyChanged
{
/// <summary>
/// Название поля.
/// </summary>
public string Name { get; } = name;
/// <summary>
/// Тип поля структуры.
/// </summary>
public abstract StructureFieldType FieldType { get; }
/// <summary>
/// Класс построения структуры данных.
/// </summary>
public StructureBuilder Builder { get; } = builder;
/// <summary>
/// Флаг, указывающий, отображается ли поле.
/// </summary>
public virtual bool Visible
{
get => _visible;
set
{
_visible = value;
OnPropertyChanged();
}
}
private bool _visible = true;
/// <summary>
/// Глубина поля структуры.
/// </summary>
public int Depth { get; } = depth;
/// <summary>
/// Получить строку, представляющую тип поля.
/// </summary>
/// <returns>Строка, представляющая тип поля.</returns>
public abstract string GetTypeString();
/// <summary>
/// Получить строку, представляющую значение поля.
/// </summary>
/// <returns>Строка, представляющая значение поля.</returns>
public abstract string GetValueString();
/// <summary>
/// Получить набор строк, используя результат функция.
/// </summary>
/// <typeparam name="T">Тип результирующей строки.</typeparam>
/// <param name="func">Функция, оборажения поля в результирующую строку.</param>
/// <returns>Коллекция, содержащая набор строк.</returns>
public virtual ICollection<T> GetRows<T>(Func<StructureField, T> func)
{
StructureField[] q = [this];
return q.Select(func).ToList();
}
/// <summary>
/// Событие изменения поля.
/// </summary>
public event PropertyChangedEventHandler? PropertyChanged;
/// <summary>
/// Запустить событие изменения поля.
/// </summary>
/// <param name="propertyName">Название поля.</param>
protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{
PropertyChanged?.Invoke(this, new(propertyName));
}
}
/// <summary>
/// Поле структуры с перечислением.
/// </summary>
/// <param name="builder">Класс построения структуры данных.</param>
/// <param name="value">Значение поля.</param>
/// <param name="name">Название поля.</param>
/// <param name="depth">Глубина поля.</param>
internal class StructureFieldEnum(StructureBuilder builder, object value, string name, int depth)
: StructureField(builder, name, depth)
{
/// <inheritdoc/>
public override StructureFieldType FieldType => StructureFieldType.Enum;
/// <summary>
/// Значение поля.
/// </summary>
public readonly object Value = value;
/// <summary>
/// Тип значения поля.
/// </summary>
public readonly Type Type = value.GetType();
/// <inheritdoc/>
public override string GetTypeString() => "enum";
/// <inheritdoc/>
public override string GetValueString() => $"{Type.Name}.{Value}";
}
/// <summary>
/// Пустое поле структуры.
/// </summary>
/// <param name="builder">Класс построения структуры данных.</param>
/// <param name="name">Название поля.</param>
/// <param name="depth">Глубина поля.</param>
internal class StructureFieldNull(StructureBuilder builder, string name, int depth)
: StructureField(builder, name, depth)
{
/// <inheritdoc/>
public override StructureFieldType FieldType => StructureFieldType.Null;
/// <inheritdoc/>
public override string GetTypeString() => "null";
/// <inheritdoc/>
public override string GetValueString() => "";
}
/// <summary>
/// Простое поле структуры.
/// </summary>
/// <param name="builder">Класс построения структуры данных.</param>
/// <param name="value">Значение поля.</param>
/// <param name="name">Название поля.</param>
/// <param name="depth">Глубина поля.</param>
internal class StructureFieldPrimitive(
StructureBuilder builder,
object value,
string name,
int depth
) : StructureField(builder, name, depth)
{
/// <inheritdoc/>
public override StructureFieldType FieldType => StructureFieldType.Primitive;
/// <summary>
/// Значение поля.
/// </summary>
public readonly object Value = value;
/// <summary>
/// Тип значения поля.
/// </summary>
public readonly Type Type = value.GetType();
/// <inheritdoc/>
public override string GetTypeString()
{
return Type.GetTypeCode(Type) switch
{
TypeCode.Boolean => "bool",
TypeCode.Int32 => "int",
TypeCode.String => "string",
TypeCode.Double => "double",
_ => Type.Name,
};
}
/// <inheritdoc/>
public override string GetValueString()
{
if (Type == typeof(string))
{
return "\"" + ((string)Value).Replace("\"", "\\\"") + "\"";
}
return Value.ToString() ?? string.Empty;
}
}
/// <summary>
/// Поле структуры с ссылкой на объект.
/// </summary>
/// <param name="builder">Класс построения структуры данных.</param>
/// <param name="name">Название поля.</param>
/// <param name="reference">Ссылка на объект.</param>
/// <param name="depth">Глубина поля.</param>
internal class StructureFieldReference(
StructureBuilder builder,
string name,
StructureFieldComplex? reference,
int depth
) : StructureField(builder, name, depth)
{
/// <summary>
/// Ссылка на объект.
/// </summary>
public StructureFieldComplex? Reference = reference;
/// <inheritdoc/>
public override StructureFieldType FieldType => StructureFieldType.Reference;
/// <inheritdoc/>
public override string GetTypeString() => Reference?.GetTypeString() ?? "???";
/// <inheritdoc/>
public override string GetValueString() => "<Reference>";
}
@@ -6,7 +6,7 @@ using System.Reflection;
using LinqToDB.Extensions;
using Pf2eModel.Model.Common.I18n;
namespace Pf2eDataScrapper.WPF.ViewModels.EntityViewStructure;
namespace Pf2eDataScrapper.WPF.EntityViewer.EntityViewStructure;
/// <summary>
/// Поле стркутуры с объектом.
@@ -36,6 +36,7 @@ internal class StructureFieldComplex : StructureField
{
_collapsed = value;
UpdateFieldVisibility();
OnPropertyChanged();
}
}
private bool _collapsed;
@@ -43,14 +44,13 @@ internal class StructureFieldComplex : StructureField
/// <inheritdoc/>
public override bool Visible
{
get => _visible;
get => base.Visible;
set
{
_visible = value;
base.Visible = value;
UpdateFieldVisibility();
}
}
private bool _visible = true;
/// <summary>
/// Конструктор класса поля структуры с объектом.
@@ -1,4 +1,4 @@
namespace Pf2eDataScrapper.WPF.ViewModels.EntityViewStructure;
namespace Pf2eDataScrapper.WPF.EntityViewer.EntityViewStructure;
/// <summary>
/// Тип поля структуры.
@@ -1,6 +1,6 @@
using System.Collections.Generic;
namespace Pf2eDataScrapper.WPF.ViewModels.EntityViewStructure;
namespace Pf2eDataScrapper.WPF.EntityViewer.EntityViewStructure;
/// <summary>
/// Класс для хранения обработанного объекта.
@@ -0,0 +1,149 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using FontAwesome.Sharp;
namespace Pf2eDataScrapper.WPF.EntityViewer.EntityViewStructure;
internal class StructureRow : INotifyPropertyChanged
{
/// <summary>
/// Отображаемая строка поля сущности.
/// </summary>
public StructureField Field { get; }
/// <summary>
/// Список типов лестницы.
/// </summary>
public List<LadderType> Ladder { get; set; } = [];
/// <summary>
/// Флаг наличия кнопки.
/// </summary>
public bool HasButton => Field.FieldType == StructureFieldType.Complex;
/// <summary>
/// Флаг, указывающий, отображается ли строка.
/// </summary>
public bool Visible => Field.Visible;
/// <summary>
/// Флаг, указывающий, отображается ли строка.
/// </summary>
public Visibility ItemVisibility => Visible ? Visibility.Visible : Visibility.Collapsed;
/// <summary>
/// Флаг, указывающий, отображается ли строка.
/// </summary>
public Visibility ButtonVisibility => HasButton ? Visibility.Visible : Visibility.Collapsed;
/// <summary>
/// Иконка кнопки.
/// </summary>
public string ButtonIcon => HasButton && !((StructureFieldComplex)Field).Collapsed ? IconChar.PlusSquare.ToChar() : IconChar.MinusSquare.ToChar();
/// <summary>
/// Глубина отображения поля.
/// </summary>
public int Depth => Field.Depth;
/// <summary>
/// Строковое представление названия поля.
/// </summary>
public string Name => Field.Name;
/// <summary>
/// Строковое представление типа поля.
/// </summary>
public string Type
{
get
{
string result = Field.GetTypeString();
if (result != "")
{
result = $@"({result})";
}
return result;
}
}
/// <summary>
/// Строковое представление значения поля.
/// </summary>
public string Value => Field.GetValueString();
/// <summary>
/// Команда переключения.
/// </summary>
public ICommand CollapseCommand { get; }
/// <summary>
/// Кониструктор класса <see cref="StructureRow"/>.
/// </summary>
/// <param name="field">Поле.</param>
public StructureRow(StructureField field)
{
Field = field;
CollapseCommand = new CollapseCommand(this);
Field.PropertyChanged += Field_PropertyChanged;
}
/// <summary>
///
/// </summary>
/// <param name="obj"></param>
private void Field_PropertyChanged(object? sender, PropertyChangedEventArgs e)
{
OnPropertyChanged(nameof(Field));
OnPropertyChanged(nameof(Visible));
OnPropertyChanged(nameof(ItemVisibility));
OnPropertyChanged(nameof(ButtonVisibility));
OnPropertyChanged(nameof(ButtonIcon));
}
/// <summary>
/// Событие изменения поля.
/// </summary>
public event Action<StructureRow, StructureField>? OnChange;
/// <summary>
/// Изменение поля.
/// </summary>
public event PropertyChangedEventHandler? PropertyChanged;
/// <summary>
/// При изменении поля.
/// </summary>
/// <param name="propertyName">Название поля.</param>
protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{
PropertyChanged?.Invoke(this, new(propertyName));
}
}
internal class CollapseCommand(StructureRow structureRow) : ICommand
{
private StructureRow StructureRow { get; } = structureRow;
public event EventHandler? CanExecuteChanged;
public bool CanExecute(object? parameter)
{
return true;
}
public void Execute(object? parameter)
{
var field = (StructureFieldComplex)StructureRow.Field;
field.Collapsed = !field.Collapsed;
}
}
@@ -1,7 +1,7 @@
using System;
using Pf2eModel.Model.Base;
namespace Pf2eDataScrapper.WPF.Stores;
namespace Pf2eDataScrapper.WPF.EntityViewer.Stores;
public class SelectedEntityStore
{
@@ -1,7 +1,7 @@
using System;
using Pf2eModel.Model.Enum;
namespace Pf2eDataScrapper.WPF.Stores;
namespace Pf2eDataScrapper.WPF.EntityViewer.Stores;
internal class SelectedEntityTypeStore
{
@@ -1,18 +1,47 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Pf2eDataScrapper.WPF.Stores;
using Pf2eDataScrapper.WPF.EntityViewer.Stores;
using Pf2eModel;
using Pf2eModel.Model.Enum;
namespace Pf2eDataScrapper.WPF.ViewModels;
namespace Pf2eDataScrapper.WPF.EntityViewer.ViewModel;
internal class EntityFormViewModel : ViewModelBase
{
#region "Конструктор"
public IServiceProvider ServiceProvider { get; }
public Pf2eDbContext Context { get; }
public EntityListViewModel DbEntityListViewModel { get; }
public ViewViewModel ViewViewModel { get; }
public SelectedEntityTypeStore SelectedEntityTypeStore { get; }
public EntityFormViewModel(
IServiceProvider serviceProvider,
Pf2eDbContext context,
EntityListViewModel entityListViewModel,
ViewViewModel viewViewModel,
SelectedEntityTypeStore selectedEntityTypeStore
)
{
ServiceProvider = serviceProvider;
Context = context;
DbEntityListViewModel = entityListViewModel;
ViewViewModel = viewViewModel;
SelectedEntityTypeStore = selectedEntityTypeStore;
Update();
}
public void Update()
{
LoadEntityTypes();
}
#endregion
#region "Выбор типа"
public IEnumerable<EntityType> EntityTypes { get; set; } = [];
public EntityType? SelectedEntityType
@@ -25,25 +54,6 @@ internal class EntityFormViewModel : ViewModelBase
}
}
public string TestText => SelectedEntityType?.ToString() ?? "null";
public EntityFormViewModel(
IServiceProvider serviceProvider,
Pf2eDbContext context,
SelectedEntityTypeStore selectedEntityTypeStore
)
{
ServiceProvider = serviceProvider;
Context = context;
SelectedEntityTypeStore = selectedEntityTypeStore;
Update();
}
public void Update()
{
LoadEntityTypes();
}
private void LoadEntityTypes()
{
EntityTypes = Context.Entities.Select(e => e.Type).Distinct().ToList();
@@ -51,4 +61,8 @@ internal class EntityFormViewModel : ViewModelBase
SelectedEntityTypeStore.SelectedEntityType = EntityTypes.Any() ? EntityTypes.First() : null;
}
#endregion
public string TestText => SelectedEntityType?.ToString() ?? "null";
}
@@ -5,14 +5,14 @@ using System.Linq;
using System.Threading;
using AngleSharp.Browser;
using LinqToDB.DataProvider.Access;
using Pf2eDataScrapper.WPF.Stores;
using Pf2eDataScrapper.WPF.EntityViewer.Stores;
using Pf2eModel;
using Pf2eModel.Model.Base;
using Pf2eModel.Model.Enum;
namespace Pf2eDataScrapper.WPF.ViewModels;
namespace Pf2eDataScrapper.WPF.EntityViewer.ViewModel;
internal class DbEntityListViewModel : ViewModelBase
internal class EntityListViewModel : ViewModelBase
{
public Pf2eDbContext Context { get; }
public SelectedEntityTypeStore SelectedEntityTypeStore { get; }
@@ -92,7 +92,7 @@ internal class DbEntityListViewModel : ViewModelBase
}
private ObservableCollection<Entity> _entities = [];
public DbEntityListViewModel(
public EntityListViewModel(
Pf2eDbContext context,
SelectedEntityTypeStore selectedEntityTypeStore,
SelectedEntityStore selectedEntityStore
@@ -106,7 +106,7 @@ internal class DbEntityListViewModel : ViewModelBase
SelectedEntityTypeStore_SelectedEntityTypeChanged;
}
~DbEntityListViewModel()
~EntityListViewModel()
{
SelectedEntityTypeStore.SelectedEntityTypeChanged -=
SelectedEntityTypeStore_SelectedEntityTypeChanged;
@@ -2,13 +2,13 @@
using System.Collections.ObjectModel;
using System.Linq;
using Pf2eDataScrapper.Helpers;
using Pf2eDataScrapper.WPF.Stores;
using Pf2eDataScrapper.WPF.ViewModels.EntityViewStructure;
using Pf2eDataScrapper.WPF.EntityViewer.EntityViewStructure;
using Pf2eDataScrapper.WPF.EntityViewer.Stores;
using Pf2eModel;
namespace Pf2eDataScrapper.WPF.ViewModels;
namespace Pf2eDataScrapper.WPF.EntityViewer.ViewModel;
internal class EntityViewViewModel : ViewModelBase
internal class ViewViewModel : ViewModelBase
{
public Pf2eDbContext Context { get; }
public SelectedEntityStore SelectedEntityStore { get; }
@@ -31,6 +31,7 @@ internal class EntityViewViewModel : ViewModelBase
{
_rows = value;
OnPropertyChanged();
}
}
private ObservableCollection<StructureRow> _rows = [];
@@ -39,7 +40,7 @@ internal class EntityViewViewModel : ViewModelBase
private readonly List<StructureRow> _allRows = [];
public EntityViewViewModel(Pf2eDbContext context, SelectedEntityStore selectedEntityStore)
public ViewViewModel(Pf2eDbContext context, SelectedEntityStore selectedEntityStore)
{
Context = context;
SelectedEntityStore = selectedEntityStore;
@@ -48,7 +49,7 @@ internal class EntityViewViewModel : ViewModelBase
SelectedEntityStore_SelectedEntityTypeChanged;
}
~EntityViewViewModel()
~ViewViewModel()
{
SelectedEntityStore.SelectedEntityTypeChanged -=
SelectedEntityStore_SelectedEntityTypeChanged;
@@ -93,6 +94,8 @@ internal class EntityViewViewModel : ViewModelBase
foreach (StructureRow row in _allRows)
{
Rows.Add(row);
row.OnChange += Row_OnChange;
}
BuildLadder();
@@ -100,6 +103,11 @@ internal class EntityViewViewModel : ViewModelBase
OnPropertyChanged(nameof(Rows));
}
private void Row_OnChange(StructureRow row, StructureField field)
{
OnPropertyChanged(nameof(Rows));
}
/// <summary>
/// Построение лестницы для строк полей структуры.
/// </summary>
@@ -143,9 +151,7 @@ internal class EntityViewViewModel : ViewModelBase
row.Ladder = ladder;
lastLadder = ladder
.Select(l => (l == LadderType.Last) ? LadderType.Through : l)
.ToList();
lastLadder = ladder.Select(l => l == LadderType.Last ? LadderType.Through : l).ToList();
}
}
}
@@ -1,63 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Pf2eDataScrapper.WPF.ViewModels.EntityViewStructure;
/// <summary>
/// Базовый класс для полей структуры.
/// </summary>
/// <param name="builder">Класс построения структуры данных.</param>
/// <param name="name">Название поля.</param>
/// <param name="depth">Глубина поля.</param>
internal abstract class StructureField(StructureBuilder builder, string name, int depth)
{
/// <summary>
/// Название поля.
/// </summary>
public readonly string Name = name;
/// <summary>
/// Тип поля структуры.
/// </summary>
public abstract StructureFieldType FieldType { get; }
/// <summary>
/// Класс построения структуры данных.
/// </summary>
public readonly StructureBuilder Builder = builder;
/// <summary>
/// Флаг, указывающий, отображается ли поле.
/// </summary>
public virtual bool Visible { get; set; } = true;
/// <summary>
/// Глубина поля структуры.
/// </summary>
public readonly int Depth = depth;
/// <summary>
/// Получить строку, представляющую тип поля.
/// </summary>
/// <returns>Строка, представляющая тип поля.</returns>
public abstract string GetTypeString();
/// <summary>
/// Получить строку, представляющую значение поля.
/// </summary>
/// <returns>Строка, представляющая значение поля.</returns>
public abstract string GetValueString();
/// <summary>
/// Получить набор строк, используя результат функция.
/// </summary>
/// <typeparam name="T">Тип результирующей строки.</typeparam>
/// <param name="func">Функция, оборажения поля в результирующую строку.</param>
/// <returns>Коллекция, содержащая набор строк.</returns>
public virtual ICollection<T> GetRows<T>(Func<StructureField, T> func)
{
StructureField[] q = [this];
return q.Select(func).ToList();
}
}
@@ -1,33 +0,0 @@
using System;
namespace Pf2eDataScrapper.WPF.ViewModels.EntityViewStructure;
/// <summary>
/// Поле структуры с перечислением.
/// </summary>
/// <param name="builder">Класс построения структуры данных.</param>
/// <param name="value">Значение поля.</param>
/// <param name="name">Название поля.</param>
/// <param name="depth">Глубина поля.</param>
internal class StructureFieldEnum(StructureBuilder builder, object value, string name, int depth)
: StructureField(builder, name, depth)
{
/// <inheritdoc/>
public override StructureFieldType FieldType => StructureFieldType.Enum;
/// <summary>
/// Значение поля.
/// </summary>
public readonly object Value = value;
/// <summary>
/// Тип значения поля.
/// </summary>
public readonly Type Type = value.GetType();
/// <inheritdoc/>
public override string GetTypeString() => "enum";
/// <inheritdoc/>
public override string GetValueString() => $"{Type.Name}.{Value}";
}
@@ -1,20 +0,0 @@
namespace Pf2eDataScrapper.WPF.ViewModels.EntityViewStructure;
/// <summary>
/// Пустое поле структуры.
/// </summary>
/// <param name="builder">Класс построения структуры данных.</param>
/// <param name="name">Название поля.</param>
/// <param name="depth">Глубина поля.</param>
internal class StructureFieldNull(StructureBuilder builder, string name, int depth)
: StructureField(builder, name, depth)
{
/// <inheritdoc/>
public override StructureFieldType FieldType => StructureFieldType.Null;
/// <inheritdoc/>
public override string GetTypeString() => "null";
/// <inheritdoc/>
public override string GetValueString() => "";
}
@@ -1,55 +0,0 @@
using System;
namespace Pf2eDataScrapper.WPF.ViewModels.EntityViewStructure;
/// <summary>
/// Простое поле структуры.
/// </summary>
/// <param name="builder">Класс построения структуры данных.</param>
/// <param name="value">Значение поля.</param>
/// <param name="name">Название поля.</param>
/// <param name="depth">Глубина поля.</param>
internal class StructureFieldPrimitive(
StructureBuilder builder,
object value,
string name,
int depth
) : StructureField(builder, name, depth)
{
/// <inheritdoc/>
public override StructureFieldType FieldType => StructureFieldType.Primitive;
/// <summary>
/// Значение поля.
/// </summary>
public readonly object Value = value;
/// <summary>
/// Тип значения поля.
/// </summary>
public readonly Type Type = value.GetType();
/// <inheritdoc/>
public override string GetTypeString()
{
return Type.GetTypeCode(Type) switch
{
TypeCode.Boolean => "bool",
TypeCode.Int32 => "int",
TypeCode.String => "string",
TypeCode.Double => "double",
_ => Type.Name,
};
}
/// <inheritdoc/>
public override string GetValueString()
{
if (Type == typeof(string))
{
return "\"" + ((string)Value).Replace("\"", "\\\"") + "\"";
}
return Value.ToString() ?? string.Empty;
}
}
@@ -1,30 +0,0 @@
namespace Pf2eDataScrapper.WPF.ViewModels.EntityViewStructure;
/// <summary>
/// Поле структуры с ссылкой на объект.
/// </summary>
/// <param name="builder">Класс построения структуры данных.</param>
/// <param name="name">Название поля.</param>
/// <param name="reference">Ссылка на объект.</param>
/// <param name="depth">Глубина поля.</param>
internal class StructureFieldReference(
StructureBuilder builder,
string name,
StructureFieldComplex? reference,
int depth
) : StructureField(builder, name, depth)
{
/// <summary>
/// Ссылка на объект.
/// </summary>
public StructureFieldComplex? Reference = reference;
/// <inheritdoc/>
public override StructureFieldType FieldType => StructureFieldType.Reference;
/// <inheritdoc/>
public override string GetTypeString() => Reference?.GetTypeString() ?? "???";
/// <inheritdoc/>
public override string GetValueString() => "<Reference>";
}
@@ -1,175 +0,0 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.Header;
using Brushes = System.Windows.Media.Brushes;
using Image = System.Windows.Controls.Image;
namespace Pf2eDataScrapper.WPF.ViewModels.EntityViewStructure;
internal class StructureRow(StructureField item)
{
/// <summary>
/// Отображаемая строка поля сущности.
/// </summary>
public StructureField Item { get; } = item;
/// <summary>
/// Список типов лестницы.
/// </summary>
public List<LadderType> Ladder { get; set; } = [];
/// <summary>
/// Флаг наличия кнопки.
/// </summary>
public bool HasButton => Item.FieldType == StructureFieldType.Complex;
/// <summary>
/// Флаг, указывающий, отображается ли строка.
/// </summary>
public bool Visible => Item.Visible;
/// <summary>
/// Флаг, указывающий, отображается ли строка.
/// </summary>
public Visibility ButtonVisibility => HasButton ? Visibility.Visible : Visibility.Collapsed;
/// <summary>
/// Глубина отображения поля.
/// </summary>
public int Depth => Item.Depth;
/// <summary>
/// Строковое представление названия поля.
/// </summary>
public string Name => Item.Name;
/// <summary>
/// Строковое представление типа поля.
/// </summary>
public string Type
{
get
{
string result = Item.GetTypeString();
if (result != "")
{
result = $@"({result})";
}
return result;
}
}
/// <summary>
/// Строковое представление значения поля.
/// </summary>
public string Value => Item.GetValueString();
}
// [ValueConversion(typeof(IEnumerable<LadderType>), typeof(Image), ParameterType = typeof(int))]
public class LadderToImageConverter : IMultiValueConverter
{
public object? Convert(
object[] value,
Type targetType,
object? parameter,
System.Globalization.CultureInfo culture
)
{
if (
value.Length != 2
|| !value[0].GetType().IsAssignableTo(typeof(IEnumerable<LadderType>))
)
{
return null;
}
IEnumerable<LadderType> ladder = (IEnumerable<LadderType>)value[0];
if (!ladder.Any())
{
return null;
}
int n = ladder.Count();
int itemHeight = (int)value[1];
DrawingGroup result = new();
result.Children.Add(
new GeometryDrawing()
{
Geometry = new RectangleGeometry(new(0, 0, n * itemHeight, itemHeight)),
Pen = new(Brushes.Transparent, 0),
}
);
result.Children.Add(
new GeometryDrawing()
{
Geometry = GetLadderGeometryGroup(ladder, itemHeight),
Pen = new(Brushes.Black, 1),
}
);
return new DrawingImage(result);
}
private GeometryGroup GetLadderGeometryGroup(IEnumerable<LadderType> ladder, int h)
{
GeometryGroup geometryGroup = new();
float h2 = h * 0.5f;
int i = 0;
foreach (LadderType ladderType in ladder)
{
switch (ladderType)
{
case LadderType.Empty:
break;
case LadderType.Last:
geometryGroup.Children.Add(
new LineGeometry(new(i * h + h2, 0), new(i * h + h2, h2))
);
geometryGroup.Children.Add(
new LineGeometry(new(i * h + h2, h2), new(i * h + h, h2))
);
break;
case LadderType.Through:
geometryGroup.Children.Add(
new LineGeometry(new(i * h + h2, 0), new(i * h + h2, h))
);
if (i == ladder.Count() - 1)
{
geometryGroup.Children.Add(
new LineGeometry(new(i * h + h2, h2), new(i * h + h, h2))
);
}
break;
default:
throw new ArgumentOutOfRangeException(nameof(ladder));
}
i++;
}
return geometryGroup;
}
public object[] ConvertBack(
object value,
Type[] targetTypes,
object parameter,
CultureInfo culture
)
{
throw new NotSupportedException();
}
}
@@ -1,5 +1,5 @@
<Window
x:Class="Pf2eDataScrapper.WPF.ProgressFormWpf"
x:Class="Pf2eDataScrapper.WPF.ProgressForm"
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"
@@ -9,13 +9,13 @@ namespace Pf2eDataScrapper.WPF;
/// <summary>
/// Логика взаимодействия для ProgressFormWpf.xaml
/// </summary>
internal partial class ProgressFormWpf : Window
internal partial class ProgressForm : Window
{
public ProcessProgress Progress { get; }
public ObservableCollection<ListViewRow> ViewRows { get; set; } = [];
public ProgressFormWpf(ProcessProgress progress)
public ProgressForm(ProcessProgress progress)
{
Progress = progress;
@@ -1,7 +1,7 @@
using Microsoft.Extensions.DependencyInjection;
using Pf2eDataScrapper.WPF.Components;
using Pf2eDataScrapper.WPF.Stores;
using Pf2eDataScrapper.WPF.ViewModels;
using Pf2eDataScrapper.WPF.EntityViewer.Stores;
using Pf2eDataScrapper.WPF.EntityViewer.ViewModel;
namespace Pf2eDataScrapper.WPF;
@@ -12,8 +12,8 @@ public static class WpfServiceProviderExtension
return collection
// ViewModels
.AddTransient<EntityFormViewModel>()
.AddTransient<DbEntityListViewModel>()
.AddTransient<EntityViewViewModel>()
.AddTransient<EntityListViewModel>()
.AddTransient<ViewViewModel>()
// Stores
.AddSingleton<SelectedEntityTypeStore>()
.AddSingleton<SelectedEntityStore>()