Skip to content
This repository was archived by the owner on Sep 25, 2024. It is now read-only.

Commit 94afbbd

Browse files
authored
Merge pull request #538 from xamarin/ermau-type-selector-fixes
Object editor / type selector fixes
2 parents 5e9aefc + 4a2adca commit 94afbbd

File tree

4 files changed

+113
-11
lines changed

4 files changed

+113
-11
lines changed

Xamarin.PropertyEditing.Tests/ObjectPropertyViewModelTests.cs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,41 @@ public async Task MultiValueTypesNull ()
256256
Assert.That (vm.ValueType, Is.Null);
257257
}
258258

259+
[Test]
260+
public void ReturnedNullTypeCancels ()
261+
{
262+
object value = new object ();
263+
var p = CreatePropertyMock ("prop");
264+
var childsubInfo = GetTypeInfo (typeof (SubChildClass));
265+
var editor = new MockObjectEditor (new[] { p.Object }, new Dictionary<IPropertyInfo, IReadOnlyList<ITypeInfo>> {
266+
{
267+
p.Object,
268+
new[] {
269+
GetTypeInfo (typeof(ChildClass)),
270+
childsubInfo
271+
}
272+
}
273+
});
274+
275+
var providerMock = CreateProviderMock (value, new MockObjectEditor { Target = value });
276+
var vm = new ObjectPropertyViewModel (new TargetPlatform (providerMock.Object), p.Object, new[] { editor });
277+
278+
var tcs = new TaskCompletionSource<ITypeInfo> ();
279+
bool requested = false;
280+
vm.TypeRequested += (sender, args) => {
281+
requested = true;
282+
args.SelectedType = tcs.Task;
283+
};
284+
285+
Assume.That (vm.CreateInstanceCommand.CanExecute (childsubInfo), Is.True);
286+
vm.CreateInstanceCommand.Execute (null);
287+
Assume.That (requested, Is.True);
288+
289+
tcs.SetResult (null);
290+
291+
providerMock.Verify (ep => ep.CreateObjectAsync (null), Times.Never);
292+
}
293+
259294
private TestContext syncContext;
260295

261296
private Mock<IEditorProvider> CreateProviderMock (object value, IObjectEditor editor)

Xamarin.PropertyEditing.Tests/SimpleCollectionViewTests.cs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,50 @@ public void Indexer ()
756756
Assert.Throws<ArgumentOutOfRangeException> (() => view[2].ToString(), "this[] didn't throw out of range on filtered out item");
757757
}
758758

759+
[Test]
760+
[Description ("Covers #522, empty parents now unfiltered by their own filter shouldn't be added")]
761+
public void ParentFilterChangesOnEmpty ()
762+
{
763+
var parents = new ObservableCollection<TestNode> {
764+
new TestNode ("A") {
765+
Children = new List<TestNode> {
766+
new TestNode ("A child")
767+
}
768+
},
769+
new TestNode ("Baz") {
770+
Children = new List<TestNode> {
771+
new TestNode ("Baz child")
772+
}
773+
},
774+
new TestNode ("Bar") {
775+
Children = new List<TestNode> {
776+
new TestNode ("Bar child")
777+
}
778+
},
779+
};
780+
781+
var view = new SimpleCollectionView (parents, new SimpleCollectionViewOptions {
782+
DisplaySelector = TestNodeDisplaySelector,
783+
ChildrenSelector = TestNodeChildrenSelector,
784+
ChildOptions = new SimpleCollectionViewOptions {
785+
DisplaySelector = TestNodeDisplaySelector
786+
}
787+
});
788+
789+
Assume.That (view.Count, Is.EqualTo (3));
790+
791+
view.Options.Filter = o => ((TestNode) o).Key != "Bar";
792+
Assume.That (view.Count, Is.EqualTo (2));
793+
794+
view.Options.ChildOptions.Filter = o => ((TestNode) o).Key.StartsWith ("A");
795+
Assume.That (view.Count, Is.EqualTo (1));
796+
797+
view.Options.Filter = null;
798+
799+
Assert.That (((KeyValuePair<string, SimpleCollectionView>) view[0]).Key, Is.EqualTo (parents[0].Key));
800+
Assert.That (view.Count, Is.EqualTo (1));
801+
}
802+
759803
private IEnumerable TestNodeChildrenSelector (object o)
760804
{
761805
return ((TestNode)o).Children;

Xamarin.PropertyEditing/ViewModels/ObjectPropertyViewModel.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,9 @@ private async void CreateInstance ()
164164

165165
try {
166166
selectedType = await args.SelectedType;
167-
} catch (OperationCanceledException) {
167+
if (selectedType == null)
168+
return;
169+
} catch (OperationCanceledException) {
168170
return;
169171
}
170172
}

Xamarin.PropertyEditing/ViewModels/SimpleCollectionView.cs

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,6 @@ public object this[int index]
127127

128128
public bool HasChildElements => (this.filtered.Count > 0);
129129

130-
public bool IsFiltering => Options?.Filter != null;
131-
132130
public bool Contains (object value)
133131
{
134132
return IndexOf (value) != -1;
@@ -289,15 +287,19 @@ private string GetKey (object element)
289287

290288
private bool MatchesFilter (Element element)
291289
{
292-
if (!IsFiltering)
290+
if (!GetIsFiltering())
291+
return true;
292+
if (element.ChildrenView != null && !element.ChildrenView.HasChildElements)
293+
return false;
294+
if (Options.Filter == null)
293295
return true;
294296

295297
return Options.Filter (element.Item);
296298
}
297299

298300
private void FilterCore (bool notify = true, bool isPureSubset = false)
299301
{
300-
if (!IsFiltering) {
302+
if (!GetIsFiltering()) {
301303
if (this.arranged.Count == this.filtered.Count)
302304
return;
303305
}
@@ -312,8 +314,7 @@ private void FilterCore (bool notify = true, bool isPureSubset = false)
312314

313315
var toRemove = new List<string>();
314316
foreach (var kvp in this.filtered) {
315-
var childView = kvp.Value.ChildrenView;
316-
if ((childView != null && !childView.HasChildElements) || !MatchesFilter (kvp.Value)) {
317+
if (!MatchesFilter (kvp.Value)) {
317318
toRemove.Add (kvp.Key);
318319
}
319320
}
@@ -324,7 +325,7 @@ private void FilterCore (bool notify = true, bool isPureSubset = false)
324325
var toAdd = new List<string> (filteredOut.Count);
325326
foreach (string key in filteredOut) {
326327
Element e = this.arranged[key];
327-
if (!IsFiltering || Options.Filter (e.Item))
328+
if (MatchesFilter (e))
328329
toAdd.Add (key);
329330
}
330331
toAdd.Sort (Comparer);
@@ -435,8 +436,6 @@ private void Reset (bool notify = true)
435436
this.arranged.Clear();
436437
this.filtered.Clear();
437438

438-
bool filtering = IsFiltering;
439-
440439
foreach (var sourceItem in this.source.Cast<object>().Select (o => new { Item = o, Key = GetKey (o) }).OrderBy (e => e.Key, Comparer)) {
441440
Element e = new Element {
442441
Item = sourceItem.Item
@@ -453,7 +452,7 @@ private void Reset (bool notify = true)
453452
e.ChildrenView = new SimpleCollectionView (children, Options.ChildOptions, this, sourceItem.Key, sourceItem.Item);
454453
}
455454

456-
if (!filtering || this.options.Filter (e.Item))
455+
if (MatchesFilter (e))
457456
this.filtered.Add (sourceItem.Key, e);
458457
}
459458

@@ -499,5 +498,27 @@ private void OnCollectionChanged (NotifyCollectionChangedEventArgs e)
499498
}
500499
}
501500
}
501+
502+
private bool GetIsFiltering ()
503+
{
504+
// Generally our hierarchy is at max 3 levels deep, this can be cached if we find it problematic
505+
SimpleCollectionView parent = this;
506+
while (parent != null) {
507+
if (parent.Options?.Filter != null)
508+
return true;
509+
510+
parent = parent.parent;
511+
}
512+
513+
SimpleCollectionViewOptions childOptions = Options.ChildOptions;
514+
while (childOptions != null) {
515+
if (childOptions.Filter != null)
516+
return true;
517+
518+
childOptions = childOptions.ChildOptions;
519+
}
520+
521+
return false;
522+
}
502523
}
503524
}

0 commit comments

Comments
 (0)