Skip to content

Commit 91b37de

Browse files
committed
Allow searching for controls and prefabs on control and prefab reference manager screen
For a large project, there can be thousands of controls and prefabs in use. Although, data grid should be able to handle these number of records without requiring pagination, we still need to allow users to search for controls and prefabs on reference manager screen.
1 parent 75f1a2a commit 91b37de

File tree

6 files changed

+142
-21
lines changed

6 files changed

+142
-21
lines changed

src/Pixel.Automation.Designer.ViewModels/VersionManager/ControlReferenceManagerViewModel.cs

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
using Dawn;
22
using Notifications.Wpf.Core;
3+
using Pixel.Automation.Core.Controls;
34
using Pixel.Automation.Core.Models;
45
using Pixel.Automation.Editor.Core.Helpers;
56
using Pixel.Automation.Editor.Core.Interfaces;
67
using Pixel.Automation.Reference.Manager;
78
using Pixel.Automation.Reference.Manager.Contracts;
9+
using Pixel.Automation.TestExplorer.ViewModels;
810
using Pixel.Persistence.Services.Client;
911
using Serilog;
1012
using System.Collections.ObjectModel;
13+
using System.ComponentModel;
14+
using System.Windows.Data;
1115

1216
namespace Pixel.Automation.Designer.ViewModels.VersionManager
1317
{
@@ -27,6 +31,25 @@ public class ControlReferenceManagerViewModel : Caliburn.Micro.Screen, IVersionM
2731
/// </summary>
2832
public ObservableCollection<ControlReferenceViewModel> References { get; private set; } = new();
2933

34+
/// <summary>
35+
/// Filter text to filter for controls
36+
/// </summary>
37+
string filterText = string.Empty;
38+
public string FilterText
39+
{
40+
get
41+
{
42+
return filterText;
43+
}
44+
set
45+
{
46+
filterText = value;
47+
var fixtureView = CollectionViewSource.GetDefaultView(References);
48+
fixtureView.Refresh();
49+
NotifyOfPropertyChange(() => FilterText);
50+
}
51+
}
52+
3053
/// <summary>
3154
/// constructor
3255
/// </summary>
@@ -41,10 +64,27 @@ public ControlReferenceManagerViewModel(IApplicationDataManager applicationDataM
4164
this.controlReferences = this.referenceManager.GetControlReferences();
4265
foreach(var reference in this.controlReferences.References)
4366
{
44-
var controls = applicationDataManager.GetControlsById(reference.ApplicationId, reference.ControlId);
45-
var controlInUse = controls.FirstOrDefault(a => a.Version.Equals(reference.Version));
46-
this.References.Add(new ControlReferenceViewModel( reference, controlInUse.ControlName , reference.Version.ToString(), controls.Select(s => s.Version)));
67+
var controls = applicationDataManager.GetControlsById(reference.ApplicationId, reference.ControlId);
68+
this.References.Add(new ControlReferenceViewModel( reference, controls));
4769
}
70+
CreateDefaultView();
71+
}
72+
73+
/// <summary>
74+
/// Setup the collection view with grouping and sorting
75+
/// </summary>
76+
private void CreateDefaultView()
77+
{
78+
var fixtureGroupedItems = CollectionViewSource.GetDefaultView(References);
79+
fixtureGroupedItems.SortDescriptions.Add(new SortDescription(nameof(ControlReferenceViewModel.ControlName), ListSortDirection.Ascending));
80+
fixtureGroupedItems.Filter = new Predicate<object>((a) =>
81+
{
82+
if (a is ControlReferenceViewModel controlReference)
83+
{
84+
return controlReference.ControlName.Contains(FilterText) || controlReference.ControlName.Equals(FilterText);
85+
}
86+
return true;
87+
});
4888
}
4989

5090
/// <summary>

src/Pixel.Automation.Designer.ViewModels/VersionManager/ControlReferenceViewModel.cs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Dawn;
22
using Pixel.Automation.Core;
3+
using Pixel.Automation.Core.Controls;
34
using Pixel.Automation.Core.Models;
45
using System.Collections.ObjectModel;
56

@@ -10,7 +11,7 @@ namespace Pixel.Automation.Designer.ViewModels.VersionManager
1011
/// </summary>
1112
public class ControlReferenceViewModel : NotifyPropertyChanged
1213
{
13-
internal readonly ControlReference controlReference;
14+
internal readonly ControlReference controlReference;
1415

1516
/// <summary>
1617
/// Name of the Control
@@ -41,6 +42,9 @@ public Version SelectedVersion
4142
}
4243
}
4344

45+
// <summary>
46+
/// Indicate if version was changed
47+
/// </summary>
4448
public bool IsDirty { get; private set; }
4549

4650
/// <summary>
@@ -55,16 +59,18 @@ public Version SelectedVersion
5559
/// <param name="controlName"></param>
5660
/// <param name="versionInUse"></param>
5761
/// <param name="availableVersions"></param>
58-
public ControlReferenceViewModel(ControlReference controlReference, string controlName, string versionInUse, IEnumerable<Version> availableVersions)
62+
public ControlReferenceViewModel(ControlReference controlReference, IEnumerable<ControlDescription> controls)
5963
{
60-
this.controlReference = Guard.Argument(controlReference).NotNull();
61-
this.ControlName = controlName;
62-
this.VersionInUse = versionInUse;
63-
foreach (var version in availableVersions)
64+
Guard.Argument(controls, nameof(controls)).NotNull().NotEmpty();
65+
this.controlReference = Guard.Argument(controlReference, nameof(controlReference)).NotNull();
66+
var controlInUse = controls.FirstOrDefault(a => a.Version.Equals(controlReference.Version));
67+
this.ControlName = controlInUse.ControlName;
68+
this.VersionInUse = controlReference.Version.ToString();
69+
foreach (var version in controls.Select(s => s.Version))
6470
{
6571
this.AvailableVersions.Add(version);
6672
}
67-
this.SelectedVersion = this.AvailableVersions.FirstOrDefault(a => a.ToString().Equals(versionInUse)) ?? this.AvailableVersions.First();
73+
this.SelectedVersion = this.AvailableVersions.FirstOrDefault(a => a.ToString().Equals(this.VersionInUse)) ?? this.AvailableVersions.First();
6874
this.IsDirty = false;
6975
}
7076
}

src/Pixel.Automation.Designer.ViewModels/VersionManager/PrefabReferenceManagerViewModel.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
using Pixel.Persistence.Services.Client.Interfaces;
88
using Serilog;
99
using System.Collections.ObjectModel;
10+
using System.ComponentModel;
11+
using System.Windows.Data;
1012

1113
namespace Pixel.Automation.Designer.ViewModels.VersionManager
1214
{
@@ -18,8 +20,30 @@ public class PrefabReferenceManagerViewModel : Caliburn.Micro.Screen, IVersionMa
1820
private readonly INotificationManager notificationManager;
1921
public readonly PrefabReferences prefabReferences;
2022

23+
/// <summary>
24+
/// Collection of <see cref="PrefabReference"/> usesd in the project
25+
/// </summary>
2126
public ObservableCollection<PrefabReferenceViewModel> PrefabReferences { get; private set; } = new();
2227

28+
/// <summary>
29+
/// Filter text to filter for prefabs
30+
/// </summary>
31+
string filterText = string.Empty;
32+
public string FilterText
33+
{
34+
get
35+
{
36+
return filterText;
37+
}
38+
set
39+
{
40+
filterText = value;
41+
var fixtureView = CollectionViewSource.GetDefaultView(PrefabReferences);
42+
fixtureView.Refresh();
43+
NotifyOfPropertyChange(() => FilterText);
44+
}
45+
}
46+
2347
public PrefabReferenceManagerViewModel(IPrefabDataManager prefabDataManager, IReferenceManager referenceManager,
2448
INotificationManager notificationManager)
2549
{
@@ -40,6 +64,24 @@ public PrefabReferenceManagerViewModel(IPrefabDataManager prefabDataManager, IRe
4064
}
4165
}
4266
}
67+
CreateDefaultView();
68+
}
69+
70+
/// <summary>
71+
/// Setup the collection view with grouping and sorting
72+
/// </summary>
73+
private void CreateDefaultView()
74+
{
75+
var fixtureGroupedItems = CollectionViewSource.GetDefaultView(PrefabReferences);
76+
fixtureGroupedItems.SortDescriptions.Add(new SortDescription(nameof(PrefabReferenceViewModel.PrefabName), ListSortDirection.Ascending));
77+
fixtureGroupedItems.Filter = new Predicate<object>((a) =>
78+
{
79+
if (a is PrefabReferenceViewModel prefabReference)
80+
{
81+
return prefabReference.PrefabName.Contains(FilterText) || prefabReference.PrefabName.Equals(FilterText);
82+
}
83+
return true;
84+
});
4385
}
4486

4587
public async Task SaveAsync()

src/Pixel.Automation.Designer.ViewModels/VersionManager/PrefabReferenceViewModel.cs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,28 @@
44
using System.Collections.ObjectModel;
55

66
namespace Pixel.Automation.Designer.ViewModels.VersionManager
7-
{
7+
{
8+
/// <summary>
9+
/// View Model wrapper for <see cref="PrefabReference"/>
10+
/// </summary>
811
public class PrefabReferenceViewModel : NotifyPropertyChanged
912
{
1013
internal readonly PrefabReference prefabReference;
1114

15+
/// <summary>
16+
/// Name of the Prefab
17+
/// </summary>
1218
public string PrefabName { get; private set; }
1319

20+
/// <summary>
21+
/// Version of prefaab used in current version of project
22+
/// </summary>
1423
public string VersionInUse { get; private set; }
1524

1625
private PrefabVersion selectedVersion;
26+
/// <summary>
27+
/// Select version of prefab on view
28+
/// </summary>
1729
public PrefabVersion SelectedVersion
1830
{
1931
get => this.selectedVersion;
@@ -29,10 +41,21 @@ public PrefabVersion SelectedVersion
2941
}
3042
}
3143

44+
/// <summary>
45+
/// Indicate if version was changed
46+
/// </summary>
3247
public bool IsDirty { get; private set; }
3348

49+
/// <summary>
50+
/// Available versions of Prefab
51+
/// </summary>
3452
public ObservableCollection<PrefabVersion> AvailableVersions { get; private set; } = new();
3553

54+
/// <summary>
55+
/// constructor
56+
/// </summary>
57+
/// <param name="prefabProject"></param>
58+
/// <param name="prefabReference"></param>
3659
public PrefabReferenceViewModel(PrefabProject prefabProject, PrefabReference prefabReference)
3760
{
3861
Guard.Argument(prefabProject).NotNull();

src/Pixel.Automation.Designer.Views/VersionManager/ControlReferenceManagerView.xaml

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,21 @@
1111
</controls:MetroWindow.Resources>
1212
<Grid>
1313
<Grid.RowDefinitions>
14-
<RowDefinition Height="*"></RowDefinition>
15-
<RowDefinition Height="90"></RowDefinition>
14+
<RowDefinition Height="Auto"></RowDefinition>
15+
<RowDefinition Height="*"></RowDefinition>
1616
<RowDefinition Height="60"></RowDefinition>
1717
</Grid.RowDefinitions>
1818

19-
<DataGrid Grid.Row="0" x:Name="References" ItemsSource="{Binding References}" MaxHeight="600"
19+
<TextBox x:Name="Filter" Grid.Row="0" Text="{Binding FilterText, UpdateSourceTrigger=PropertyChanged}"
20+
controls:TextBoxHelper.ClearTextButton="True" controls:TextBoxHelper.UseFloatingWatermark="True"
21+
controls:TextBoxHelper.Watermark="Search" HorizontalAlignment="Left" MinWidth="400"
22+
VerticalAlignment="Top" Margin="15,20,10,10"></TextBox>
23+
24+
<DataGrid Grid.Row="1" x:Name="References" ItemsSource="{Binding References}" MaxHeight="600"
2025
CanUserSortColumns="True" CanUserAddRows="False" CanUserResizeRows="False" CanUserResizeColumns="True"
2126
Grid.Column="1" GridLinesVisibility="All"
2227
Margin="10" Padding="5" ScrollViewer.HorizontalScrollBarVisibility="Disabled"
23-
AutoGenerateColumns="False"
28+
AutoGenerateColumns="False" EnableRowVirtualization="True"
2429
RowHeaderWidth="0" HorizontalAlignment="Center" VerticalAlignment="Top">
2530
<DataGrid.Columns>
2631
<DataGridTemplateColumn Header="Control Name">

src/Pixel.Automation.Designer.Views/VersionManager/PrefabReferenceManagerView.xaml

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
44
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
55
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
6-
xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
7-
xmlns:local="clr-namespace:Pixel.Automation.Designer.Views.VersionManager"
6+
xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
87
xmlns:controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
98
mc:Ignorable="d" WindowStartupLocation="CenterScreen" SizeToContent="WidthAndHeight"
109
d:DesignHeight="450" d:DesignWidth="800" MinHeight="450">
@@ -13,16 +12,22 @@
1312
</controls:MetroWindow.Resources>
1413
<Grid>
1514
<Grid.RowDefinitions>
15+
<RowDefinition Height="Auto"></RowDefinition>
1616
<RowDefinition Height="*"></RowDefinition>
1717
<RowDefinition Height="60"></RowDefinition>
1818
<RowDefinition Height="60"></RowDefinition>
1919
</Grid.RowDefinitions>
2020

21-
<DataGrid Grid.Row="0" x:Name="PrefabReferences" ItemsSource="{Binding PrefabReferences}" MaxHeight="600"
21+
<TextBox x:Name="Filter" Grid.Row="0" Text="{Binding FilterText, UpdateSourceTrigger=PropertyChanged}"
22+
controls:TextBoxHelper.ClearTextButton="True" controls:TextBoxHelper.UseFloatingWatermark="True"
23+
controls:TextBoxHelper.Watermark="Search" HorizontalAlignment="Left" MinWidth="400"
24+
VerticalAlignment="Top" Margin="15,20,10,10"></TextBox>
25+
26+
<DataGrid Grid.Row="1" x:Name="PrefabReferences" ItemsSource="{Binding PrefabReferences}" MaxHeight="600"
2227
CanUserSortColumns="True" CanUserAddRows="False" CanUserResizeRows="False" CanUserResizeColumns="True"
2328
Grid.Column="1" GridLinesVisibility="All"
2429
Margin="10" Padding="5" ScrollViewer.HorizontalScrollBarVisibility="Disabled"
25-
AutoGenerateColumns="False"
30+
AutoGenerateColumns="False" EnableRowVirtualization="True"
2631
RowHeaderWidth="0" HorizontalAlignment="Center" VerticalAlignment="Top">
2732
<DataGrid.Columns>
2833
<DataGridTemplateColumn Header="Prefab Name">
@@ -53,13 +58,13 @@
5358
</DataGrid.Columns>
5459
</DataGrid>
5560

56-
<StackPanel Grid.Row="1" x:Name="WarningPanel" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="{StaticResource ControlMargin}"
61+
<StackPanel Grid.Row="2" x:Name="WarningPanel" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="{StaticResource ControlMargin}"
5762
Background="{DynamicResource MahApps.Brushes.ValidationSummary3}" Orientation="Horizontal">
5863
<iconPacks:PackIconMaterial Kind="Alert" Margin="10,0,0,0" VerticalAlignment="Center"/>
5964
<TextBlock x:Name="WarningMessage" Margin="10,0,0,0" VerticalAlignment="Center"
6065
Text="Upgrading Prefab version can be a breaking change. You might need to redo input and output mapping script for Prefab."/>
6166
</StackPanel>
62-
<DockPanel Grid.Row="2" LastChildFill="False">
67+
<DockPanel Grid.Row="3" LastChildFill="False">
6368
<Border DockPanel.Dock="Top" BorderThickness="1" Height="1" HorizontalAlignment="Stretch" Width="{Binding Path=Width,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DockPanel}}}" BorderBrush="{DynamicResource MahApps.Brushes.Accent}"/>
6469
<Button x:Name="CloseAsync" Content="CANCEL" Width="100" DockPanel.Dock="Right" Margin="{StaticResource ControlMargin}" Style="{DynamicResource MahApps.Styles.Button.Square}"/>
6570
<Button x:Name="SaveAsync" Content="Save" DockPanel.Dock="Right" Width="100" Margin="{StaticResource ControlMargin}" Style="{DynamicResource MahApps.Styles.Button.Square.Accent}"/>

0 commit comments

Comments
 (0)