Пагинация запросов и исправление отображений

This commit is contained in:
2025-04-18 22:47:25 +04:00
parent 29aee61d4c
commit db432929bf
3 changed files with 249 additions and 38 deletions
+43 -23
View File
@@ -4,7 +4,9 @@ using Newtonsoft.Json.Linq;
using Pf2eModel; using Pf2eModel;
using Pf2eModel.Model; using Pf2eModel.Model;
using Pf2eModel.Model.Base; using Pf2eModel.Model.Base;
using Pf2eModel.Model.Base.Source;
using Pf2eModel.Model.Structure; using Pf2eModel.Model.Structure;
using System.ComponentModel;
namespace Pf2eViewer; namespace Pf2eViewer;
internal class EntityConverter : JsonConverter internal class EntityConverter : JsonConverter
@@ -16,44 +18,62 @@ internal class EntityConverter : JsonConverter
return objectType == typeof(Entity) || objectType.IsAssignableTo(typeof(IEntity)); return objectType == typeof(Entity) || objectType.IsAssignableTo(typeof(IEntity));
} }
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) private Dictionary<string, object?> DictionarySerialization(object source)
{ {
JToken token = JToken.FromObject(value!); Dictionary<string, object?> dictionary = [];
if (token.Type != JTokenType.Object) foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(source))
{ {
token.WriteTo(writer); object? v = property.GetValue(source);
return; dictionary.Add(property.Name, v);
} }
JObject obj = (JObject) token; return dictionary;
}
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
{
Dictionary<string, object?> dictionary = DictionarySerialization(value!);
if (value.GetType() != typeof(Entity))
{
dictionary.Remove("Entity");
}
switch (value) switch (value)
{ {
case Entity e: case Entity entity:
obj = ProcessEntity(obj, e); ProcessEntity(dictionary, entity);
break;
case Trait trait:
ProcessTrait(dictionary, trait);
break; break;
} }
obj.WriteTo(writer); writer.WriteStartObject();
}
private JObject ProcessEntity(JObject obj, Entity e) foreach (KeyValuePair<string, object> keyValuePair in dictionary)
{
List<int> traitIds = e.Traits.Select(t => t.Id).ToList();
List<Trait> traits = _context.Traits.Where(t => traitIds.Contains(t.Id)).Include(t => t.Entity).ToList();
foreach (JToken item in (JArray) obj.SelectToken("Traits")!)
{ {
JObject o = (JObject) item; writer.WritePropertyName(keyValuePair.Key, true);
int id = o.SelectToken("Id")!.ToObject<int>(); serializer.Serialize(writer, keyValuePair.Value);
o.Add("Name", traits.FirstOrDefault(t => t.Id == id)!.Entity.Name);
} }
obj.Remove("Description"); writer.WriteEndObject();
}
return obj;
private void ProcessTrait(Dictionary<string, object?> dictionary, Trait trait)
{
string name = trait.Entity?.Name ?? _context.Entities.Where(e => e.Id == trait.Id).Select(e => e.Name).FirstOrDefault()!;
dictionary.Remove("Entity");
dictionary.Remove("Entities");
dictionary.Add("Name", name);
}
private void ProcessEntity(Dictionary<string, object?> dictionary, Entity entity)
{
dictionary.Remove("Description");
} }
public override bool CanRead => false; public override bool CanRead => false;
+107 -10
View File
@@ -32,6 +32,13 @@ partial class MainViewForm
InnerSplitContainer = new SplitContainer(); InnerSplitContainer = new SplitContainer();
TypesListBox = new ListBox(); TypesListBox = new ListBox();
EntityGridView = new DataGridView(); EntityGridView = new DataGridView();
PaginationPagel = new Panel();
PageTextBox = new TextBox();
PaginationLabel = new TextBox();
LastPageButton = new Button();
NextPageButton = new Button();
PrevPageButton = new Button();
FirstPageButton = new Button();
ResultSplitContainer = new SplitContainer(); ResultSplitContainer = new SplitContainer();
EntityTreeView = new TreeView(); EntityTreeView = new TreeView();
DescriptionTextBox = new TextBox(); DescriptionTextBox = new TextBox();
@@ -44,6 +51,7 @@ partial class MainViewForm
InnerSplitContainer.Panel2.SuspendLayout(); InnerSplitContainer.Panel2.SuspendLayout();
InnerSplitContainer.SuspendLayout(); InnerSplitContainer.SuspendLayout();
((System.ComponentModel.ISupportInitialize) EntityGridView).BeginInit(); ((System.ComponentModel.ISupportInitialize) EntityGridView).BeginInit();
PaginationPagel.SuspendLayout();
((System.ComponentModel.ISupportInitialize) ResultSplitContainer).BeginInit(); ((System.ComponentModel.ISupportInitialize) ResultSplitContainer).BeginInit();
ResultSplitContainer.Panel1.SuspendLayout(); ResultSplitContainer.Panel1.SuspendLayout();
ResultSplitContainer.Panel2.SuspendLayout(); ResultSplitContainer.Panel2.SuspendLayout();
@@ -66,7 +74,7 @@ partial class MainViewForm
RootSplitContainer.Panel2.Controls.Add(ResultSplitContainer); RootSplitContainer.Panel2.Controls.Add(ResultSplitContainer);
RootSplitContainer.Panel2MinSize = 400; RootSplitContainer.Panel2MinSize = 400;
RootSplitContainer.Size = new Size(1181, 688); RootSplitContainer.Size = new Size(1181, 688);
RootSplitContainer.SplitterDistance = 200; RootSplitContainer.SplitterDistance = 254;
RootSplitContainer.TabIndex = 0; RootSplitContainer.TabIndex = 0;
// //
// InnerSplitContainer // InnerSplitContainer
@@ -83,8 +91,9 @@ partial class MainViewForm
// InnerSplitContainer.Panel2 // InnerSplitContainer.Panel2
// //
InnerSplitContainer.Panel2.Controls.Add(EntityGridView); InnerSplitContainer.Panel2.Controls.Add(EntityGridView);
InnerSplitContainer.Size = new Size(200, 688); InnerSplitContainer.Panel2.Controls.Add(PaginationPagel);
InnerSplitContainer.SplitterDistance = 274; InnerSplitContainer.Size = new Size(254, 688);
InnerSplitContainer.SplitterDistance = 102;
InnerSplitContainer.TabIndex = 1; InnerSplitContainer.TabIndex = 1;
// //
// TypesListBox // TypesListBox
@@ -94,7 +103,7 @@ partial class MainViewForm
TypesListBox.ItemHeight = 15; TypesListBox.ItemHeight = 15;
TypesListBox.Location = new Point(0, 0); TypesListBox.Location = new Point(0, 0);
TypesListBox.Name = "TypesListBox"; TypesListBox.Name = "TypesListBox";
TypesListBox.Size = new Size(200, 274); TypesListBox.Size = new Size(254, 102);
TypesListBox.TabIndex = 0; TypesListBox.TabIndex = 0;
TypesListBox.SelectedIndexChanged += TypesListBox_SelectedIndexChanged; TypesListBox.SelectedIndexChanged += TypesListBox_SelectedIndexChanged;
// //
@@ -105,17 +114,96 @@ partial class MainViewForm
EntityGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells; EntityGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
EntityGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize; EntityGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
EntityGridView.Dock = DockStyle.Fill; EntityGridView.Dock = DockStyle.Fill;
EntityGridView.Location = new Point(0, 0); EntityGridView.Location = new Point(0, 53);
EntityGridView.MultiSelect = false; EntityGridView.MultiSelect = false;
EntityGridView.Name = "EntityGridView"; EntityGridView.Name = "EntityGridView";
EntityGridView.ReadOnly = true; EntityGridView.ReadOnly = true;
EntityGridView.RowHeadersVisible = false; EntityGridView.RowHeadersVisible = false;
EntityGridView.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.AutoSizeToDisplayedHeaders; EntityGridView.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.AutoSizeToDisplayedHeaders;
EntityGridView.ShowEditingIcon = false; EntityGridView.ShowEditingIcon = false;
EntityGridView.Size = new Size(200, 410); EntityGridView.Size = new Size(254, 529);
EntityGridView.TabIndex = 0; EntityGridView.TabIndex = 0;
EntityGridView.RowStateChanged += EntityGridView_RowStateChanged; EntityGridView.RowStateChanged += EntityGridView_RowStateChanged;
// //
// PaginationPagel
//
PaginationPagel.Controls.Add(PageTextBox);
PaginationPagel.Controls.Add(PaginationLabel);
PaginationPagel.Controls.Add(LastPageButton);
PaginationPagel.Controls.Add(NextPageButton);
PaginationPagel.Controls.Add(PrevPageButton);
PaginationPagel.Controls.Add(FirstPageButton);
PaginationPagel.Dock = DockStyle.Top;
PaginationPagel.Location = new Point(0, 0);
PaginationPagel.Name = "PaginationPagel";
PaginationPagel.Size = new Size(254, 53);
PaginationPagel.TabIndex = 1;
//
// PageTextBox
//
PageTextBox.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
PageTextBox.Location = new Point(81, 4);
PageTextBox.Name = "PageTextBox";
PageTextBox.Size = new Size(92, 23);
PageTextBox.TabIndex = 8;
PageTextBox.Text = "1";
PageTextBox.TextAlign = HorizontalAlignment.Center;
PageTextBox.KeyPress += PageTextBox_KeyPress;
//
// PaginationLabel
//
PaginationLabel.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
PaginationLabel.BorderStyle = BorderStyle.None;
PaginationLabel.Location = new Point(3, 31);
PaginationLabel.Name = "PaginationLabel";
PaginationLabel.ReadOnly = true;
PaginationLabel.Size = new Size(248, 16);
PaginationLabel.TabIndex = 7;
PaginationLabel.Text = "Всего";
PaginationLabel.TextAlign = HorizontalAlignment.Center;
//
// LastPageButton
//
LastPageButton.Anchor = AnchorStyles.Top | AnchorStyles.Right;
LastPageButton.Location = new Point(218, 3);
LastPageButton.Name = "LastPageButton";
LastPageButton.Size = new Size(33, 23);
LastPageButton.TabIndex = 3;
LastPageButton.Text = ">>";
LastPageButton.UseVisualStyleBackColor = true;
LastPageButton.Click += LastPageButton_Click;
//
// NextPageButton
//
NextPageButton.Anchor = AnchorStyles.Top | AnchorStyles.Right;
NextPageButton.Location = new Point(179, 3);
NextPageButton.Name = "NextPageButton";
NextPageButton.Size = new Size(33, 23);
NextPageButton.TabIndex = 2;
NextPageButton.Text = ">";
NextPageButton.UseVisualStyleBackColor = true;
NextPageButton.Click += NextPageButton_Click;
//
// PrevPageButton
//
PrevPageButton.Location = new Point(42, 3);
PrevPageButton.Name = "PrevPageButton";
PrevPageButton.Size = new Size(33, 23);
PrevPageButton.TabIndex = 1;
PrevPageButton.Text = "<";
PrevPageButton.UseVisualStyleBackColor = true;
PrevPageButton.Click += PrevPageButton_Click;
//
// FirstPageButton
//
FirstPageButton.Location = new Point(3, 3);
FirstPageButton.Name = "FirstPageButton";
FirstPageButton.Size = new Size(33, 23);
FirstPageButton.TabIndex = 0;
FirstPageButton.Text = "<<";
FirstPageButton.UseVisualStyleBackColor = true;
FirstPageButton.Click += FirstPageButton_Click;
//
// ResultSplitContainer // ResultSplitContainer
// //
ResultSplitContainer.Dock = DockStyle.Fill; ResultSplitContainer.Dock = DockStyle.Fill;
@@ -129,8 +217,8 @@ partial class MainViewForm
// ResultSplitContainer.Panel2 // ResultSplitContainer.Panel2
// //
ResultSplitContainer.Panel2.Controls.Add(DescriptionTextBox); ResultSplitContainer.Panel2.Controls.Add(DescriptionTextBox);
ResultSplitContainer.Size = new Size(977, 688); ResultSplitContainer.Size = new Size(923, 688);
ResultSplitContainer.SplitterDistance = 495; ResultSplitContainer.SplitterDistance = 467;
ResultSplitContainer.TabIndex = 1; ResultSplitContainer.TabIndex = 1;
// //
// EntityTreeView // EntityTreeView
@@ -138,7 +226,7 @@ partial class MainViewForm
EntityTreeView.Dock = DockStyle.Fill; EntityTreeView.Dock = DockStyle.Fill;
EntityTreeView.Location = new Point(0, 0); EntityTreeView.Location = new Point(0, 0);
EntityTreeView.Name = "EntityTreeView"; EntityTreeView.Name = "EntityTreeView";
EntityTreeView.Size = new Size(495, 688); EntityTreeView.Size = new Size(467, 688);
EntityTreeView.TabIndex = 0; EntityTreeView.TabIndex = 0;
// //
// DescriptionTextBox // DescriptionTextBox
@@ -149,7 +237,7 @@ partial class MainViewForm
DescriptionTextBox.Name = "DescriptionTextBox"; DescriptionTextBox.Name = "DescriptionTextBox";
DescriptionTextBox.ReadOnly = true; DescriptionTextBox.ReadOnly = true;
DescriptionTextBox.ScrollBars = ScrollBars.Vertical; DescriptionTextBox.ScrollBars = ScrollBars.Vertical;
DescriptionTextBox.Size = new Size(478, 688); DescriptionTextBox.Size = new Size(452, 688);
DescriptionTextBox.TabIndex = 0; DescriptionTextBox.TabIndex = 0;
// //
// MainViewForm // MainViewForm
@@ -169,6 +257,8 @@ partial class MainViewForm
((System.ComponentModel.ISupportInitialize) InnerSplitContainer).EndInit(); ((System.ComponentModel.ISupportInitialize) InnerSplitContainer).EndInit();
InnerSplitContainer.ResumeLayout(false); InnerSplitContainer.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize) EntityGridView).EndInit(); ((System.ComponentModel.ISupportInitialize) EntityGridView).EndInit();
PaginationPagel.ResumeLayout(false);
PaginationPagel.PerformLayout();
ResultSplitContainer.Panel1.ResumeLayout(false); ResultSplitContainer.Panel1.ResumeLayout(false);
ResultSplitContainer.Panel2.ResumeLayout(false); ResultSplitContainer.Panel2.ResumeLayout(false);
ResultSplitContainer.Panel2.PerformLayout(); ResultSplitContainer.Panel2.PerformLayout();
@@ -186,4 +276,11 @@ partial class MainViewForm
private TreeView EntityTreeView; private TreeView EntityTreeView;
private SplitContainer ResultSplitContainer; private SplitContainer ResultSplitContainer;
private TextBox DescriptionTextBox; private TextBox DescriptionTextBox;
private Panel PaginationPagel;
private Button LastPageButton;
private Button NextPageButton;
private Button PrevPageButton;
private Button FirstPageButton;
private TextBox PageTextBox;
private TextBox PaginationLabel;
} }
+99 -5
View File
@@ -1,6 +1,8 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using Pf2eModel; using Pf2eModel;
using Pf2eModel.Model; using Pf2eModel.Model;
using Pf2eModel.Model.Base; using Pf2eModel.Model.Base;
@@ -29,10 +31,32 @@ public partial class MainViewForm : Form
TypesListBox.SelectedIndex = 0; TypesListBox.SelectedIndex = 0;
} }
private void TypesListBox_SelectedIndexChanged(object sender, EventArgs _) public const int PerPage = 20;
public int Count;
public int Page
{ {
if (TypesListBox.SelectedItem is null) get => Convert.ToInt32(PageTextBox.Text);
set
{ {
PageTextBox.Text = value.ToString();
UpdateTreeView();
}
}
public int MaxPage => Convert.ToInt32(Math.Ceiling(1.0 * Count / PerPage));
private void UpdateTreeView()
{
EntityType type = (EntityType) TypesListBox.SelectedItem!;
Count = Context.Entities.Count(e => e.Type == type);
if (Page < 1 || Page > MaxPage)
{
Page = Math.Min(MaxPage, Math.Max(1, Page));
return; return;
} }
@@ -40,15 +64,71 @@ public partial class MainViewForm : Form
.Where(e => e.Type == (EntityType) TypesListBox.SelectedItem) .Where(e => e.Type == (EntityType) TypesListBox.SelectedItem)
.OrderBy(e => e.Id) .OrderBy(e => e.Id)
.Include(e => e.Sources) .Include(e => e.Sources)
.ThenInclude(s => s.Source)
.Include(e => e.Aliases) .Include(e => e.Aliases)
.Include(e => e.Keywords) .Include(e => e.Keywords)
.Include(e => e.Externals) .Include(e => e.Externals)
.ThenInclude(x => x.Target)
.Include(e => e.Traits) .Include(e => e.Traits)
.ThenInclude(t => t.Entity)
.Select(e => new EntityGridRow(e)) .Select(e => new EntityGridRow(e))
.Skip((Page - 1) * PerPage)
.Take(PerPage)
.ToList(); .ToList();
EntityGridView.Rows[0].Selected = true; EntityGridView.Rows[0].Selected = true;
PaginationLabel.Text = $"Всего: {Count} объектов, {MaxPage} страниц";
FirstPageButton.Enabled = Page > 1;
PrevPageButton.Enabled = Page > 1;
NextPageButton.Enabled = Page < MaxPage;
LastPageButton.Enabled = Page < MaxPage;
} }
private void TypesListBox_SelectedIndexChanged(object sender, EventArgs _)
{
if (TypesListBox.SelectedItem is null)
{
return;
}
Page = 1;
}
private void FirstPageButton_Click(object sender, EventArgs e)
{
Page = 1;
}
private void PrevPageButton_Click(object sender, EventArgs e)
{
Page--;
}
private void NextPageButton_Click(object sender, EventArgs e)
{
Page++;
}
private void LastPageButton_Click(object sender, EventArgs e)
{
Page = MaxPage;
}
private void PageTextBox_KeyPress(object sender, KeyPressEventArgs e)
{
if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar))
{
e.Handled = true;
}
if (e.KeyChar == (char) Keys.Return)
{
UpdateTreeView();
}
}
private void EntityGridView_RowStateChanged(object sender, DataGridViewRowStateChangedEventArgs e) private void EntityGridView_RowStateChanged(object sender, DataGridViewRowStateChangedEventArgs e)
{ {
int rowsCount = EntityGridView.SelectedRows.Count; int rowsCount = EntityGridView.SelectedRows.Count;
@@ -72,18 +152,31 @@ public partial class MainViewForm : Form
{ {
JsonSerializerSettings settings = new() JsonSerializerSettings settings = new()
{ {
Converters = [new EntityConverter()] Converters = [
new EntityConverter(),
new StringEnumConverter { NamingStrategy = new CamelCaseNamingStrategy() },
]
}; };
string result = JsonConvert.SerializeObject(entity, settings); string result = JsonConvert.SerializeObject(entity, settings);
Type type = EntityOfTypeAttribute.Resolve(entity); Type type = EntityOfTypeAttribute.Resolve(entity);
string subResult = JsonConvert.SerializeObject(Context.Find(type, entity.Id), settings); string subResult = JsonConvert.SerializeObject(ResolveEntity(entity), settings);
return result[..^1] + $",\"SubEntity\":{subResult}}}"; return result[..^1] + $",\"SubEntity\":{subResult}}}";
} }
public IEntity? ResolveEntity(Entity entity)
{
switch (entity.Type)
{
case EntityType.Ancestry:
return Context.Ancestries
.FirstOrDefault(e => e.Id == entity.Id);
}
return null;
}
public static void JsonToTreeview(TreeView treeView, string jsonString, string rootName) public static void JsonToTreeview(TreeView treeView, string jsonString, string rootName)
{ {
@@ -92,11 +185,11 @@ public partial class MainViewForm : Form
: JObject.Parse(jsonString); : JObject.Parse(jsonString);
treeView.Nodes.Clear(); treeView.Nodes.Clear();
foreach (TreeNode node in Element2TreeNode(json, rootName).Nodes) foreach (TreeNode node in Element2TreeNode(json, rootName).Nodes)
{ {
treeView.Nodes.Add(node); treeView.Nodes.Add(node);
} }
treeView.ExpandAll();
} }
private static TreeNode Element2TreeNode(object element, string text = "") private static TreeNode Element2TreeNode(object element, string text = "")
@@ -156,4 +249,5 @@ public partial class MainViewForm : Form
public Entity GetEntity() => _e; public Entity GetEntity() => _e;
} }
} }