Properties added

This commit is contained in:
retr0volkov
2025-07-09 14:27:45 +03:00 Unverified
parent 72dc9b6874
commit 2a8f8d2714
10 changed files with 272 additions and 22 deletions
+3
View File
@@ -12,6 +12,9 @@ public class Property
[Required] [Required]
public string Name { get; set; } = string.Empty; public string Name { get; set; } = string.Empty;
public string Value { get; set; } = string.Empty; public string Value { get; set; } = string.Empty;
// EF stuff
public Property? Parent { get; set; }
public List<Property> Properties{ get; set; } = [];
public List<Models.Point> Points { get; set; } = []; public List<Models.Point> Points { get; set; } = [];
public List<Equipment> Equipment { get; } = []; public List<Equipment> Equipment { get; } = [];
} }
+5
View File
@@ -38,6 +38,11 @@ public class AppDbContext : DbContext
.HasMany(e => e.Properties) .HasMany(e => e.Properties)
.WithMany(e => e.Equipment); .WithMany(e => e.Equipment);
modelBuilder.Entity<Property>()
.HasMany(e => e.Properties)
.WithOne(e => e.Parent)
.HasForeignKey(e => e.ParentId);
// Equipment // Equipment
modelBuilder.Entity<Equipment>() modelBuilder.Entity<Equipment>()
.HasOne(e => e.Point) .HasOne(e => e.Point)
+40 -4
View File
@@ -1,9 +1,12 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using GazpromApp.Models; using GazpromApp.Models;
namespace GazpromApp.ViewModels; namespace GazpromApp.ViewModels;
public partial class PropertyViewModel : ViewModelBase public partial class PropertyViewModel : ViewModelBase
{ {
[ObservableProperty] [ObservableProperty]
@@ -12,17 +15,50 @@ public partial class PropertyViewModel : ViewModelBase
[ObservableProperty] [ObservableProperty]
private string _value; private string _value;
public ObservableCollection<PropertyViewModel> Properties { get; set; } = []; public ObservableCollection<PropertyViewModel> Properties { get; set; }
// Visual and other properties
public PropertyViewModel? Parent { get; set; }
[ObservableProperty]
private bool _isEditing;
public Property GetProperty(Property? parent = null)
{
Property p = new Property
{
Name = Name,
Value = Value,
Properties = [],
Parent = parent
};
p.Properties = Properties.Select(e => e.GetProperty(p)).ToList();
return p;
}
public PropertyViewModel() public PropertyViewModel()
{ {
Name = string.Empty; Name = "Имя свойства";
Value = string.Empty; Value = "Значение свойства";
Properties = [];
Parent = null;
} }
public PropertyViewModel(Property property) public PropertyViewModel(Property property, PropertyViewModel? parent = null)
{ {
Name = property.Name; Name = property.Name;
Value = property.Value; Value = property.Value;
Properties = new ObservableCollection<PropertyViewModel>(
property.Properties.Select(e => new PropertyViewModel(e, this)));
Parent = property.Parent is null ? null : parent;
}
public PropertyViewModel(PropertyViewModel property)
{
Name = "Имя свойства";
Value = "Значение свойства";
Properties = [];
Parent = property;
} }
} }
+24 -2
View File
@@ -116,19 +116,39 @@ public partial class EditEquipmentDialogViewModel : ViewModelBase
Inspections.Remove(inspection); Inspections.Remove(inspection);
} }
public ObservableCollection<PropertyViewModel> Properties { get; set; }
[RelayCommand]
private void AddPropertySimple() => Properties.Add(new PropertyViewModel());
[RelayCommand]
private static void AddProperty(PropertyViewModel property) => property.Properties.Add(new PropertyViewModel(property));
[RelayCommand]
private static void EditProperty(PropertyViewModel property) => property.IsEditing = !property.IsEditing;
[RelayCommand]
private void DeleteProperty(PropertyViewModel property)
{
if (property.Parent is null)
Properties.Remove(property);
else
property.Parent?.Properties.Remove(property);
}
private bool CanCompleteEdit() => !string.IsNullOrWhiteSpace(Name); private bool CanCompleteEdit() => !string.IsNullOrWhiteSpace(Name);
[RelayCommand(CanExecute = nameof(CanCompleteEdit))] [RelayCommand(CanExecute = nameof(CanCompleteEdit))]
private void CompleteEdit() private void CompleteEdit()
{ {
IsClosed = true; IsClosed = true;
Equipment equipment = new Equipment() Equipment equipment = new Equipment
{ {
Name = Name, Name = Name,
Description = Description, Description = Description,
Image = Image?.GetImage(), Image = Image?.GetImage(),
Inspections = Inspections.Select(e => e.GetInspection()).ToList(), Inspections = Inspections.Select(e => e.GetInspection()).ToList(),
Properties = [], Properties = Properties.Select(e => e.GetProperty()).ToList(),
}; };
WeakReferenceMessenger.Default.Send(new EditEquipmentDone(new EquipmentViewModel(equipment))); WeakReferenceMessenger.Default.Send(new EditEquipmentDone(new EquipmentViewModel(equipment)));
} }
@@ -160,6 +180,7 @@ public partial class EditEquipmentDialogViewModel : ViewModelBase
Description = "Testing"; Description = "Testing";
Image = null; Image = null;
Inspections = []; Inspections = [];
Properties = [];
IsImageSelected = false; IsImageSelected = false;
@@ -172,6 +193,7 @@ public partial class EditEquipmentDialogViewModel : ViewModelBase
Description = equipment.Description; Description = equipment.Description;
Image = equipment.Image; Image = equipment.Image;
Inspections = new ObservableCollection<InspectionViewModel>(equipment.Inspections.Select(e => e)); Inspections = new ObservableCollection<InspectionViewModel>(equipment.Inspections.Select(e => e));
Properties = new ObservableCollection<PropertyViewModel>(equipment.Properties.Select(e => e));
IsImageSelected = equipment.Image is { Bytes.Length: > 0 }; IsImageSelected = equipment.Image is { Bytes.Length: > 0 };
+77 -5
View File
@@ -89,10 +89,7 @@ public partial class EditPointDialogViewModel : ViewModelBase
} }
[RelayCommand] [RelayCommand]
private static async Task ViewImage(ImageViewModel image) private static async Task ViewImage(ImageViewModel image) => _ = await WeakReferenceMessenger.Default.Send(new ViewImageMessage(image));
{
_ = await WeakReferenceMessenger.Default.Send(new ViewImageMessage(image));
}
public ObservableCollection<EquipmentViewModel> Equipment { get; set; } public ObservableCollection<EquipmentViewModel> Equipment { get; set; }
@@ -122,6 +119,26 @@ public partial class EditPointDialogViewModel : ViewModelBase
IsEquipmentEmpty = Equipment.Count == 0; IsEquipmentEmpty = Equipment.Count == 0;
} }
public ObservableCollection<PropertyViewModel> Properties { get; set; }
[RelayCommand]
private void AddPropertySimple() => Properties.Add(new PropertyViewModel());
[RelayCommand]
private static void AddProperty(PropertyViewModel property) => property.Properties.Add(new PropertyViewModel(property));
[RelayCommand]
private static void EditProperty(PropertyViewModel property) => property.IsEditing = !property.IsEditing;
[RelayCommand]
private void DeleteProperty(PropertyViewModel property)
{
if (property.Parent is null)
Properties.Remove(property);
else
property.Parent?.Properties.Remove(property);
}
private bool CanCompleteEdit() => !string.IsNullOrWhiteSpace(Name); private bool CanCompleteEdit() => !string.IsNullOrWhiteSpace(Name);
[RelayCommand(CanExecute = nameof(CanCompleteEdit))] [RelayCommand(CanExecute = nameof(CanCompleteEdit))]
@@ -133,7 +150,8 @@ public partial class EditPointDialogViewModel : ViewModelBase
Name = Name, Name = Name,
Description = Description, Description = Description,
Images = Images.Select(e => e.GetImage()).ToList(), Images = Images.Select(e => e.GetImage()).ToList(),
Equipment = Equipment.Select(e => e.GetEquipment()).ToList() Equipment = Equipment.Select(e => e.GetEquipment()).ToList(),
Properties = Properties.Select(e => e.GetProperty()).ToList(),
}; };
WeakReferenceMessenger.Default.Send(new EditPointDone(new PointViewModel(point))); WeakReferenceMessenger.Default.Send(new EditPointDone(new PointViewModel(point)));
} }
@@ -175,6 +193,59 @@ public partial class EditPointDialogViewModel : ViewModelBase
Description = "Really big description for the equipment to show the long textReally big description for the equipment to show the long textReally big description for the equipment to show the long textReally big description for the equipment to show the long text", Image = null Description = "Really big description for the equipment to show the long textReally big description for the equipment to show the long textReally big description for the equipment to show the long textReally big description for the equipment to show the long text", Image = null
} }
]; ];
Properties = [
new PropertyViewModel
{
Name = "Property Name",
Value = "Property Value",
Properties = [
new PropertyViewModel
{
Name = "Property Name",
Value = "Property Value",
Properties = [
new PropertyViewModel
{
Name = "Property Name",
Value = "Property Value",
Properties = [],
Parent = null
},
new PropertyViewModel
{
Name = "Property Name",
Value = "Property Value",
Properties = [],
Parent = null
},
new PropertyViewModel
{
Name = "Property Name",
Value = "Property Value",
Properties = [],
Parent = null
}
],
Parent = null
},
new PropertyViewModel
{
Name = "Property Name",
Value = "Property Value",
Properties = [],
Parent = null
},
],
Parent = null
},
new PropertyViewModel
{
Name = "Property Name",
Value = "Property Value",
Properties = [],
Parent = null
}
];
IsImagesEmpty = true; IsImagesEmpty = true;
IsEquipmentEmpty = true; IsEquipmentEmpty = true;
@@ -188,6 +259,7 @@ public partial class EditPointDialogViewModel : ViewModelBase
Description = point.Description; Description = point.Description;
Images = new ObservableCollection<ImageViewModel>((point.Images ?? []).Select(e => new ImageViewModel(e))); Images = new ObservableCollection<ImageViewModel>((point.Images ?? []).Select(e => new ImageViewModel(e)));
Equipment = new ObservableCollection<EquipmentViewModel>((point.Equipment ?? []).Select(e => new EquipmentViewModel(e))); Equipment = new ObservableCollection<EquipmentViewModel>((point.Equipment ?? []).Select(e => new EquipmentViewModel(e)));
Properties = new ObservableCollection<PropertyViewModel>((point.Properties ?? []).Select(e => new PropertyViewModel(e)));
IsImagesEmpty = Images.Count == 0; IsImagesEmpty = Images.Count == 0;
IsEquipmentEmpty = Equipment.Count == 0; IsEquipmentEmpty = Equipment.Count == 0;
+53 -2
View File
@@ -18,6 +18,7 @@
<vm:EditEquipmentDialogViewModel/> <vm:EditEquipmentDialogViewModel/>
</Design.DataContext> </Design.DataContext>
<Window.Resources> <Window.Resources>
<!-- ReSharper disable once Xaml.RedundantResource -->
<ResourceDictionary> <ResourceDictionary>
<ResourceDictionary.ThemeDictionaries> <ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Light"> <ResourceDictionary x:Key="Light">
@@ -129,15 +130,65 @@
</DataTemplate> </DataTemplate>
</ItemsRepeater.ItemTemplate> </ItemsRepeater.ItemTemplate>
</ItemsRepeater> </ItemsRepeater>
<Button HorizontalAlignment="Center" Margin="10" <Button HorizontalAlignment="Center" Margin="10" Width="30" Height="30"
Command="{Binding AddInspectionCommand}"> Command="{Binding AddInspectionCommand}">
<Image Width="24" Source="avares://GazpromApp/Assets/ic_fluent_add_24_filled (Custom).png"/> <Image Width="24" Height="24" Source="avares://GazpromApp/Assets/ic_fluent_add_24_filled (Custom).png"/>
</Button> </Button>
</StackPanel> </StackPanel>
</ScrollViewer> </ScrollViewer>
</TabItem> </TabItem>
<TabItem Header="Свойства"> <TabItem Header="Свойства">
<ScrollViewer>
<StackPanel>
<TreeView ItemsSource="{Binding Properties}">
<TreeView.DataTemplates>
<TreeDataTemplate DataType="{x:Type vm:PropertyViewModel}"
ItemsSource="{Binding Properties}">
<Grid ColumnDefinitions="150,*,Auto,Auto,Auto">
<TextBlock Grid.Column="0" FontSize="18" VerticalAlignment="Center"
IsVisible="{Binding !IsEditing}"
Text="{Binding Name}"/>
<TextBox Grid.Column="0"
IsVisible="{Binding IsEditing}"
Text="{Binding Name}"/>
<TextBlock Grid.Column="1" FontSize="18" VerticalAlignment="Center"
IsVisible="{Binding !IsEditing}"
Text="{Binding Value}"/>
<TextBox Grid.Column="1"
IsVisible="{Binding IsEditing}"
Text="{Binding Value}"/>
<Button Grid.Column="2" Width="30" Height="30" Margin="4" VerticalAlignment="Center"
Command="{Binding #Root.((vm:EditEquipmentDialogViewModel)DataContext).AddPropertyCommand}"
CommandParameter="{Binding .}">
<Image Width="24" Height="24" Source="avares://GazpromApp/Assets/ic_fluent_add_24_filled (Custom).png"/>
</Button>
<Button Grid.Column="3" Width="30" Height="30" Margin="4" VerticalAlignment="Center"
Command="{Binding #Root.((vm:EditEquipmentDialogViewModel)DataContext).EditPropertyCommand}"
CommandParameter="{Binding .}">
<Panel>
<Image Width="24" Height="24" Source="avares://GazpromApp/Assets/ic_fluent_edit_24_filled (Custom).png"
IsVisible="{Binding !IsEditing}"/>
<Image Width="24" Height="24" Source="avares://GazpromApp/Assets/ic_fluent_save_24_filled (Custom).png"
IsVisible="{Binding IsEditing}"/>
</Panel>
</Button>
<Button Grid.Column="4" Width="30" Height="30" Margin="4" VerticalAlignment="Center"
Command="{Binding #Root.((vm:EditEquipmentDialogViewModel)DataContext).DeletePropertyCommand}"
CommandParameter="{Binding .}">
<Image Height="24" Width="24" Source="avares://GazpromApp/Assets/ic_fluent_delete_24_filled (Custom).png"/>
</Button>
</Grid>
</TreeDataTemplate>
</TreeView.DataTemplates>
</TreeView>
<Button HorizontalAlignment="Center" Margin="10" Width="30" Height="30"
Command="{Binding AddPropertySimpleCommand}">
<Image Height="24" Width="24" Source="avares://GazpromApp/Assets/ic_fluent_add_24_filled (Custom).png"/>
</Button>
</StackPanel>
</ScrollViewer>
</TabItem> </TabItem>
</TabControl> </TabControl>
+64 -3
View File
@@ -16,6 +16,20 @@
<Design.DataContext> <Design.DataContext>
<vm:EditPointDialogViewModel/> <vm:EditPointDialogViewModel/>
</Design.DataContext> </Design.DataContext>
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Light">
<SolidColorBrush x:Key="BackgroundBrush" Color="#f0f0f0"/>
<SolidColorBrush x:Key="BorderBrush" Color="#d3d3d3"/>
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<SolidColorBrush x:Key="BackgroundBrush" Color="#101010"/>
<SolidColorBrush x:Key="BorderBrush" Color="#303030"/>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid RowDefinitions="70,150,*,Auto" ColumnDefinitions="*,100,220" x:Name="Root"> <Grid RowDefinitions="70,150,*,Auto" ColumnDefinitions="*,100,220" x:Name="Root">
<TextBlock Grid.Column="0" Grid.Row="0" FontSize="28" Margin="20,4,0,4" <TextBlock Grid.Column="0" Grid.Row="0" FontSize="28" Margin="20,4,0,4"
Text="{Binding Name}" Text="{Binding Name}"
@@ -89,16 +103,17 @@
<ScrollViewer> <ScrollViewer>
<StackPanel> <StackPanel>
<ItemsRepeater <ItemsRepeater
IsVisible="{Binding !IsEquipmentEmpty}"
ItemsSource="{Binding Equipment}"> ItemsSource="{Binding Equipment}">
<ItemsRepeater.Layout> <ItemsRepeater.Layout>
<StackLayout Orientation="Vertical"/> <StackLayout Orientation="Vertical"/>
</ItemsRepeater.Layout> </ItemsRepeater.Layout>
<ItemsRepeater.ItemTemplate> <ItemsRepeater.ItemTemplate>
<DataTemplate DataType="vm:EquipmentViewModel"> <DataTemplate DataType="vm:EquipmentViewModel">
<Expander HorizontalAlignment="Stretch" Margin="0,4,0,4"> <Expander HorizontalAlignment="Stretch" Margin="0,4,0,4"
Background="{DynamicResource BackgroundBrush}"
BorderBrush="{DynamicResource BorderBrush}">
<Expander.Header> <Expander.Header>
<Grid Height="54" HorizontalAlignment="Left" <Grid Height="54" HorizontalAlignment="Stretch"
ColumnDefinitions="52, 300, *, Auto"> ColumnDefinitions="52, 300, *, Auto">
<Image Height="50" Width="50" Margin="0,2,2,2" HorizontalAlignment="Center" Stretch="Uniform" <Image Height="50" Width="50" Margin="0,2,2,2" HorizontalAlignment="Center" Stretch="Uniform"
Source="{Binding Image.FileName, FallbackValue=null}"/> Source="{Binding Image.FileName, FallbackValue=null}"/>
@@ -142,7 +157,53 @@
<TabItem Header="Свойства"> <TabItem Header="Свойства">
<ScrollViewer> <ScrollViewer>
<StackPanel> <StackPanel>
<TreeView ItemsSource="{Binding Properties}">
<TreeView.DataTemplates>
<TreeDataTemplate DataType="{x:Type vm:PropertyViewModel}"
ItemsSource="{Binding Properties}">
<Grid ColumnDefinitions="150,*,Auto,Auto,Auto">
<TextBlock Grid.Column="0" FontSize="18" VerticalAlignment="Center"
IsVisible="{Binding !IsEditing}"
Text="{Binding Name}"/>
<TextBox Grid.Column="0"
IsVisible="{Binding IsEditing}"
Text="{Binding Name}"/>
<TextBlock Grid.Column="1" FontSize="18" VerticalAlignment="Center"
IsVisible="{Binding !IsEditing}"
Text="{Binding Value}"/>
<TextBox Grid.Column="1"
IsVisible="{Binding IsEditing}"
Text="{Binding Value}"/>
<Button Grid.Column="2" Width="30" Height="30" Margin="4" VerticalAlignment="Center"
Command="{Binding #Root.((vm:EditPointDialogViewModel)DataContext).AddPropertyCommand}"
CommandParameter="{Binding .}">
<Image Width="24" Height="24" Source="avares://GazpromApp/Assets/ic_fluent_add_24_filled (Custom).png"/>
</Button>
<Button Grid.Column="3" Width="30" Height="30" Margin="4" VerticalAlignment="Center"
Command="{Binding #Root.((vm:EditPointDialogViewModel)DataContext).EditPropertyCommand}"
CommandParameter="{Binding .}">
<Panel>
<Image Width="24" Height="24" Source="avares://GazpromApp/Assets/ic_fluent_edit_24_filled (Custom).png"
IsVisible="{Binding !IsEditing}"/>
<Image Width="24" Height="24" Source="avares://GazpromApp/Assets/ic_fluent_save_24_filled (Custom).png"
IsVisible="{Binding IsEditing}"/>
</Panel>
</Button>
<Button Grid.Column="4" Width="30" Height="30" Margin="4" VerticalAlignment="Center"
Command="{Binding #Root.((vm:EditPointDialogViewModel)DataContext).DeletePropertyCommand}"
CommandParameter="{Binding .}">
<Image Height="24" Width="24" Source="avares://GazpromApp/Assets/ic_fluent_delete_24_filled (Custom).png"/>
</Button>
</Grid>
</TreeDataTemplate>
</TreeView.DataTemplates>
</TreeView>
<Button HorizontalAlignment="Center" Margin="10" Width="30" Height="30"
Command="{Binding AddPropertySimpleCommand}">
<Image Height="24" Width="24" Source="avares://GazpromApp/Assets/ic_fluent_add_24_filled (Custom).png"/>
</Button>
</StackPanel> </StackPanel>
</ScrollViewer> </ScrollViewer>
</TabItem> </TabItem>
Binary file not shown.
+1 -1
View File
@@ -13,7 +13,7 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("GazpromApp")] [assembly: System.Reflection.AssemblyCompanyAttribute("GazpromApp")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+646f60e800da077d6f0e380695010dafc74187f1")] [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+72dc9b68743bc32f202a106f6161f2a4c5401a0c")]
[assembly: System.Reflection.AssemblyProductAttribute("GazpromApp")] [assembly: System.Reflection.AssemblyProductAttribute("GazpromApp")]
[assembly: System.Reflection.AssemblyTitleAttribute("GazpromApp")] [assembly: System.Reflection.AssemblyTitleAttribute("GazpromApp")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
@@ -1 +1 @@
d96ce4087b396be689d2265a12a73a6073c44823fe98e991f0bc173e827a4fb3 15ad954b97553ac87ab7a0c39a3000dca500a7ad2febeb4c503529c5bb6ac55b