Skip to content

Commit 592be06

Browse files
committed
Added ItemTemplateSelector and ItemContainerStyle properties to SuggestBox and improved CachedPathSuggestionDemo
1 parent 3af62f7 commit 592be06

18 files changed

+761
-270
lines changed

source/Demos/CachedPathSuggestBoxDemo/Infrastructure/CachedPathInformationSuggest.cs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77

88
namespace CachedPathSuggestBoxDemo.Infrastructure
99
{
10-
10+
/// <summary>
11+
/// Wraps a LiteDB to generate previously bookmarked suggestions through similarity for a given string.
12+
/// </summary>
1113
public class CachedPathInformationSuggest : ISuggest
1214
{
1315
private static readonly int NumberOfResultsReturned = 5;
@@ -25,6 +27,11 @@ public void Insert(string path)
2527
LiteRepository.Instance.Insert(directoryInfo.FullName);
2628
}
2729

30+
internal void Delete(string text)
31+
{
32+
throw new NotImplementedException();
33+
}
34+
2835
/// <summary>
2936
/// Makes suggestions of paths based on match between query and the full-name of the path.
3037
/// Only returns latest <see cref="NumberOfResultsReturned"/> results (newest first).
@@ -39,13 +46,13 @@ public void Insert(string path)
3946
/// f:\\do_letters
4047
/// g:\\document\lists.ico
4148
/// </example>
42-
public async Task<IEnumerable<object>?> MakeSuggestions(string queryThis)
49+
public async Task<IEnumerable<ViewModels.List.BaseItem>?> MakeSuggestions(string queryThis)
4350
{
4451
return await Task.Run(() => MakeSuggestionsPrivate().ToArray());
4552

46-
IEnumerable<object> MakeSuggestionsPrivate() =>
53+
IEnumerable<ViewModels.List.BaseItem> MakeSuggestionsPrivate() =>
4754
from item in GetPathInformations(queryThis)
48-
select new { Header = item.FullName, Value = item.FullName };
55+
select new ViewModels.List.Item( item.FullName, item.FullName );
4956

5057
static PathInformation[] GetPathInformations(string key)
5158
{
Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,68 @@
11
#nullable enable
2-
using System;
32
using System.Collections.Generic;
43
using System.Linq;
5-
using System.Text;
64
using System.Threading.Tasks;
75

86
namespace CachedPathSuggestBoxDemo.Infrastructure
97
{
8+
/// <summary>
9+
/// Wraps a LiteDB and a FileSystem data provider to generate similarity based suggestions
10+
/// for a given string.
11+
/// </summary>
1012
class CombinedSuggest : ISuggest
1113
{
1214
private readonly DirectorySuggest directorySuggest = new DirectorySuggest();
1315

14-
public readonly CachedPathInformationSuggest CachedPathInformationSuggest = new CachedPathInformationSuggest();
16+
private readonly CachedPathInformationSuggest CachedPathInformationSuggest = new CachedPathInformationSuggest();
1517

16-
public async Task<IEnumerable<object>?> MakeSuggestions(string queryThis)
18+
/// <summary>
19+
/// Gets a list of combined suggestions based on string similarity from the:
20+
/// 1) cached entries (bookmarks) and
21+
/// 2) file system data provider.
22+
/// </summary>
23+
/// <param name="queryThis"></param>
24+
/// <returns>
25+
/// Both types (cached entries and file system provider entries) of entries are returned
26+
/// in a single list. The list contains a separator item (if both types of items are returned).
27+
/// The separator item can be used for visual enhancement when displaying the list.
28+
/// </returns>
29+
public async Task<IEnumerable<ViewModels.List.BaseItem>?> MakeSuggestions(string queryThis)
1730
{
18-
1931
var suggestions1 = (await CachedPathInformationSuggest.MakeSuggestions(queryThis))?.ToArray();
2032

2133
var suggestions2 = (await directorySuggest.MakeSuggestions(queryThis))?.ToArray();
2234

23-
if (suggestions2 == null && suggestions1?.Any() == false)
24-
{
35+
if (suggestions2?.Length == 0 && suggestions1?.Any() == false)
2536
return null;
26-
}
2737

28-
return suggestions2 != null ?
29-
suggestions1?.Concat(suggestions2) :
30-
suggestions1;
38+
if (suggestions2?.Length != 0 && suggestions1?.Any() == false)
39+
return suggestions2;
40+
41+
if (suggestions2?.Length == 0 && suggestions1?.Any() == true)
42+
return suggestions1;
43+
44+
// Insert a seperator between bookmarked suggestions and suggestions from file system
45+
return suggestions1
46+
.Concat(new ViewModels.List.BaseItem[1] { new ViewModels.List.ItemSeperator() })
47+
.Concat(suggestions2);
48+
}
49+
50+
/// <summary>
51+
/// Insert a new suggestion into the available list of suggestions
52+
/// </summary>
53+
/// <param name="text"></param>
54+
public void InsertCachedSuggestion(string text)
55+
{
56+
CachedPathInformationSuggest.Insert(text);
57+
}
58+
59+
/// <summary>
60+
/// Delete a suggestion in the available list of suggestions
61+
/// </summary>
62+
/// <param name="text"></param>
63+
public void DeleteCachedSuggestion(string text)
64+
{
65+
CachedPathInformationSuggest.Delete(text);
3166
}
3267
}
3368
}

source/Demos/CachedPathSuggestBoxDemo/Infrastructure/DirectorySuggestSource.cs

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010
namespace CachedPathSuggestBoxDemo.Infrastructure
1111
{
1212
/// <summary>
13-
/// Defines a suggestion object to generate suggestions
14-
/// based on sub entries of specified string.
13+
/// Wraps a LiteDB and a FileSystem data provider to generate similarity based suggestions
14+
/// for a given string.
15+
///
16+
/// Defines a suggestion object to generate suggestions based on sub entries of specified string.
1517
/// </summary>
1618
public class DirectorySuggest : ISuggest
1719
{
@@ -31,7 +33,7 @@ public DirectorySuggest()
3133
}
3234
#endregion ctors
3335

34-
public async Task<IEnumerable<object>?> MakeSuggestions(string queryThis)
36+
public async Task<IEnumerable<ViewModels.List.BaseItem>?> MakeSuggestions(string queryThis)
3537
{
3638
// Cancel current task(s) if there is any...
3739
var queueList = _Queue.Values.ToList();
@@ -67,9 +69,7 @@ public DirectorySuggest()
6769

6870
return null;
6971

70-
71-
72-
static IEnumerable<object>? EnumerateSubDirs(string input)
72+
static IEnumerable<ViewModels.List.Item>? EnumerateSubDirs(string input)
7373
{
7474
if (string.IsNullOrEmpty(input))
7575
return EnumerateLogicalDrives();
@@ -80,7 +80,7 @@ public DirectorySuggest()
8080

8181
// Find last separator and list directories underneath
8282
// with * search-pattern
83-
IEnumerable<object> Get()
83+
IEnumerable<ViewModels.List.Item> Get()
8484
{
8585
int sepIdx = input.LastIndexOf('\\');
8686

@@ -98,24 +98,23 @@ IEnumerable<object> Get()
9898
}
9999

100100
if (directories == null) return EnumerateLogicalDrives();
101-
var dirs = new List<object>();
101+
var dirs = new List<ViewModels.List.Item>();
102102

103103
foreach (var t in directories)
104-
dirs.Add(new { Header = t, Value = t });
104+
dirs.Add(new ViewModels.List.Item (t, t ));
105105

106106
return dirs;
107107
}
108108
}
109109

110-
static IEnumerable<object> EnumerateDrives(string input)
110+
static IEnumerable<ViewModels.List.Item> EnumerateDrives(string input)
111111
{
112112
if (string.IsNullOrEmpty(input))
113113
return EnumerateLogicalDrives();
114114

115115
return EnumeratePaths(input) ?? EnumerateLogicalDrives();
116116

117-
118-
static IEnumerable<object>? EnumeratePaths(string input) => input.Length switch
117+
static IEnumerable<ViewModels.List.Item>? EnumeratePaths(string input) => input.Length switch
119118
{
120119
1 when char.ToUpper(input[0]) >= 'A' && char.ToUpper(input[0]) <= 'Z' =>
121120
EnumerateLogicalDriveOrSubDirs(input + ":\\", input),
@@ -124,19 +123,18 @@ 2 when char.ToUpper(input[1]) == ':' &&
124123
char.ToUpper(input[0]) >= 'A' && char.ToUpper(input[0]) <= 'Z' =>
125124
EnumerateLogicalDriveOrSubDirs(input + "\\", input),
126125

127-
2 => new List<object>(),
126+
2 => new List<ViewModels.List.Item>(),
128127

129128
_ when (char.ToUpper(input[1]) == ':' &&
130129
char.ToUpper(input[2]) == '\\' &&
131130
char.ToUpper(input[0]) >= 'A' && char.ToUpper(input[0]) <= 'Z') =>
132131
// Check if we know this drive and list it with sub-folders if we do
133132
EnumerateLogicalDriveOrSubDirs(input, input),
134-
_ => new List<object>()
133+
_ => new List<ViewModels.List.Item>()
135134
};
136135
}
137136

138-
139-
static IEnumerable<object> EnumerateLogicalDrives()
137+
static IEnumerable<ViewModels.List.Item> EnumerateLogicalDrives()
140138
{
141139
foreach (var driveName in Environment.GetLogicalDrives()
142140
.Where(driveName => string.IsNullOrEmpty(driveName) == false))
@@ -155,29 +153,28 @@ static IEnumerable<object> EnumerateLogicalDrives()
155153
header = driveName;
156154
}
157155

158-
yield return new { Header = header, Value = driveName };
156+
yield return new ViewModels.List.Item (header, driveName );
159157
}
160158
}
161159

162-
static IEnumerable<object>? EnumerateLogicalDriveOrSubDirs(string testDrive, string input)
160+
static IEnumerable<ViewModels.List.Item>? EnumerateLogicalDriveOrSubDirs(string testDrive, string input)
163161
{
164162
return System.IO.Directory.Exists(testDrive) ?
165163
GetDirectories(testDrive) is { } array ?
166164
GetLogicalDriveOrSubDirs2(testDrive, input, array) :
167165
null :
168166
null;
169167

170-
171-
static IEnumerable<object>? GetLogicalDriveOrSubDirs2(string testDrive, string input, IEnumerable<string> directories)
168+
static IEnumerable<ViewModels.List.Item>? GetLogicalDriveOrSubDirs2(string testDrive, string input, IEnumerable<string> directories)
172169
{
173170
// List the drive itself if there was only 1 or 2 letters
174171
// since this is not a valid drive and we don'nt know if the user
175172
// wants to go to the drive or a folder contained in it
176173
if (input.Length <= 2)
177-
yield return new { Header = testDrive, Value = testDrive };
174+
yield return new ViewModels.List.Item(testDrive, testDrive );
178175

179176
foreach (var item in directories)
180-
yield return new { Header = item, Value = item };
177+
yield return new ViewModels.List.Item(item, item );
181178
}
182179

183180
static string[]? GetDirectories(string testDrive)

source/Demos/CachedPathSuggestBoxDemo/Infrastructure/ISuggest.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,14 @@
55

66
namespace CachedPathSuggestBoxDemo.Infrastructure
77
{
8+
/// <summary>
9+
/// Defines an interface to make similarity based suggestions for a given string.
10+
/// </summary>
811
public interface ISuggest
912
{
1013
/// <summary>
1114
/// Makes suggestions based on <see cref="queryThis"/>
1215
/// </summary>
13-
Task<IEnumerable<object>?> MakeSuggestions(string queryThis);
16+
Task<IEnumerable<ViewModels.List.BaseItem>?> MakeSuggestions(string queryThis);
1417
}
1518
}

source/Demos/CachedPathSuggestBoxDemo/Infrastructure/LiteRepository.cs

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,65 @@
77

88
namespace CachedPathSuggestBoxDemo.Infrastructure
99
{
10+
/// <summary>
11+
/// Implements a static service provider for searching and editing a LiteDB file.
12+
/// </summary>
1013
public sealed class LiteRepository
1114
{
15+
#region fields
1216
private const string DbPath = @"..\..\..\Data\KeyValue.litedb";
1317

1418
// Collection needs a name because object, keyvaluepair<string,string> is generic.
1519
private const string CollectionName = "collection";
20+
#endregion fields
1621

17-
// Explicit static constructor to tell C# compiler
18-
// not to mark type as beforefieldinit
22+
#region ctors
23+
/// <summary>
24+
/// Explicit static constructor to tell C# compiler
25+
/// not to mark type as beforefieldinit
26+
/// </summary>
1927
static LiteRepository()
2028
{
2129
}
2230

31+
/// <summary>
32+
/// Class constructor
33+
/// </summary>
34+
private LiteRepository()
35+
{
36+
Directory.GetParent(DbPath).Create();
37+
38+
// Id needed to ensure Upsert works.
39+
BsonMapper.Global.Entity<KeyValuePair<string, string>>().Id(x => x.Value);
40+
}
41+
#endregion ctors
42+
43+
/// <summary>
44+
/// Gets the repository instance from this static instance.
45+
/// </summary>
46+
public static LiteRepository Instance { get; } = new LiteRepository();
47+
48+
/// <summary>
49+
/// Inserts a new string into the collection of bookmarked strings.
50+
/// </summary>
51+
/// <param name="k"></param>
52+
/// <param name="collectionName"></param>
2353
public void Insert(string k, string? collectionName = null)
2454
{
2555
using var db = new LiteDatabase(DbPath);
2656
var col = db.GetCollection<KeyValuePair<string, DateTime>>(collectionName ?? CollectionName);
57+
58+
// Make sure string is not already present
2759
col.Upsert(new KeyValuePair<string, DateTime>(k, DateTime.Now));
2860
}
2961

62+
/// <summary>
63+
/// Filters the collection of bookmark strings by the given string and
64+
/// returns the resulting collection.
65+
/// </summary>
66+
/// <param name="key"></param>
67+
/// <param name="collectionName"></param>
68+
/// <returns></returns>
3069
public IEnumerable<KeyValuePair<string, DateTime>> Filter(string key, string? collectionName = null)
3170
{
3271
using var db = new LiteDatabase(DbPath);
@@ -35,17 +74,5 @@ public IEnumerable<KeyValuePair<string, DateTime>> Filter(string key, string? co
3574
col.Query().ToArray() :
3675
col.Find(Query.Contains(nameof(KeyValuePair<string, DateTime>.Key), key)).ToArray();
3776
}
38-
39-
private LiteRepository()
40-
{
41-
Directory.GetParent(DbPath).Create();
42-
43-
// Id needed to ensure Upsert works.
44-
BsonMapper.Global.Entity<KeyValuePair<string, string>>()
45-
.Id(x => x.Value);
46-
47-
}
48-
49-
public static LiteRepository Instance { get; } = new LiteRepository();
5077
}
5178
}

source/Demos/CachedPathSuggestBoxDemo/Infrastructure/PathInformation.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,15 @@
33

44
namespace CachedPathSuggestBoxDemo.Infrastructure
55
{
6+
/// <summary>
7+
/// Implements a simple path information object to keep track of its full name and path etc.
8+
/// </summary>
69
public class PathInformation : IEquatable<PathInformation>
710
{
11+
/// <summary>
12+
/// Class constructor
13+
/// </summary>
14+
/// <param name="argValue"></param>
815
public PathInformation(string argValue)
916
{
1017
Name = new DirectoryInfo(argValue).Parent == null ? argValue :
@@ -14,8 +21,14 @@ public PathInformation(string argValue)
1421
FullName = argValue;
1522
}
1623

24+
/// <summary>
25+
/// Gets the name of a directory (without the path)
26+
/// </summary>
1727
public string Name { get; }
1828

29+
/// <summary>
30+
/// Gets the full name (including path) for a directory
31+
/// </summary>
1932
public string FullName { get; }
2033

2134

0 commit comments

Comments
 (0)