[UWP] Fixed code to only call ReloadData once, set CVS to null, and add correct items to internal source (#3023) fixes #3008 fixes #3009 fixes #3018 fixes #3019 fixes #2996
* fixes #3008 and #3009 * fixed code to only call reload data once * if itemsource is set to null then just null out CVS otherwise it'll cause a COM Exception * added ListView Categories to some tests to more easily run targeted tests against UWP * fixed a couple UWP tests that weren't passing * * fixes #3018 * fixes #3019 * fixes #2996 * The wrong object was being added to the internal collection * * add test case for listview initailized as null
This commit is contained in:
Родитель
092947adb5
Коммит
19f6d75004
|
@ -12,6 +12,7 @@ using Xamarin.Forms.Internals;
|
||||||
#if UITEST
|
#if UITEST
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using Xamarin.UITest;
|
using Xamarin.UITest;
|
||||||
|
using Xamarin.Forms.Core.UITests;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace Xamarin.Forms.Controls
|
namespace Xamarin.Forms.Controls
|
||||||
|
@ -318,6 +319,9 @@ namespace Xamarin.Forms.Controls.Issues
|
||||||
{
|
{
|
||||||
[Preserve(AllMembers = true)]
|
[Preserve(AllMembers = true)]
|
||||||
[Issue(IssueTracker.None, 0, "Adding Multiple Items to a ListView", PlatformAffected.All)]
|
[Issue(IssueTracker.None, 0, "Adding Multiple Items to a ListView", PlatformAffected.All)]
|
||||||
|
#if UITEST
|
||||||
|
[NUnit.Framework.Category(UITestCategories.ListView)]
|
||||||
|
#endif
|
||||||
public class AddingMultipleItemsListView : TestContentPage
|
public class AddingMultipleItemsListView : TestContentPage
|
||||||
{
|
{
|
||||||
protected override void Init()
|
protected override void Init()
|
||||||
|
|
|
@ -10,12 +10,16 @@ using System;
|
||||||
#if UITEST
|
#if UITEST
|
||||||
using Xamarin.UITest;
|
using Xamarin.UITest;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using Xamarin.Forms.Core.UITests;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace Xamarin.Forms.Controls.Issues
|
namespace Xamarin.Forms.Controls.Issues
|
||||||
{
|
{
|
||||||
[Preserve(AllMembers = true)]
|
[Preserve(AllMembers = true)]
|
||||||
[Issue(IssueTracker.Bugzilla, 56771, "Multi-item add in INotifyCollectionChanged causes a NSInternalInconsistencyException in bindings on iOS", PlatformAffected.iOS)]
|
[Issue(IssueTracker.Bugzilla, 56771, "Multi-item add in INotifyCollectionChanged causes a NSInternalInconsistencyException in bindings on iOS", PlatformAffected.iOS)]
|
||||||
|
#if UITEST
|
||||||
|
[NUnit.Framework.Category(UITestCategories.ListView)]
|
||||||
|
#endif
|
||||||
public class Bugzilla56771 : TestContentPage
|
public class Bugzilla56771 : TestContentPage
|
||||||
{
|
{
|
||||||
const string Success = "Success";
|
const string Success = "Success";
|
||||||
|
|
|
@ -8,12 +8,16 @@ using Xamarin.Forms.Internals;
|
||||||
#if UITEST
|
#if UITEST
|
||||||
using Xamarin.UITest;
|
using Xamarin.UITest;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using Xamarin.Forms.Core.UITests;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace Xamarin.Forms.Controls.Issues
|
namespace Xamarin.Forms.Controls.Issues
|
||||||
{
|
{
|
||||||
[Preserve(AllMembers = true)]
|
[Preserve(AllMembers = true)]
|
||||||
[Issue(IssueTracker.None, 5955, "Group ListView Crashes when ItemSource is Cleared", PlatformAffected.iOS)]
|
[Issue(IssueTracker.None, 5955, "Group ListView Crashes when ItemSource is Cleared", PlatformAffected.iOS)]
|
||||||
|
#if UITEST
|
||||||
|
[Category(UITestCategories.ListView)]
|
||||||
|
#endif
|
||||||
public class GroupListViewHeaderIndexOutOfRange : TestContentPage
|
public class GroupListViewHeaderIndexOutOfRange : TestContentPage
|
||||||
{
|
{
|
||||||
const string ButtonId = "button";
|
const string ButtonId = "button";
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
#if UITEST
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
using Xamarin.UITest;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using Xamarin.UITest.Queries;
|
||||||
|
|
||||||
|
namespace Xamarin.Forms.Controls.Issues
|
||||||
|
{
|
||||||
|
public static class UITestHelper
|
||||||
|
{
|
||||||
|
public static string ReadText(this AppResult result) =>
|
||||||
|
result.Text ?? result.Description;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -135,23 +135,23 @@ namespace Xamarin.Forms.Controls.Issues
|
||||||
RunningApp.WaitForElement(q => q.Marked(A));
|
RunningApp.WaitForElement(q => q.Marked(A));
|
||||||
RunningApp.Tap(q => q.Marked(A));
|
RunningApp.Tap(q => q.Marked(A));
|
||||||
|
|
||||||
Assert.AreEqual(A, RunningApp.WaitForElement(q => q.Marked(lblItem))[0].Text);
|
Assert.AreEqual(A, RunningApp.WaitForElement(q => q.Marked(lblItem))[0].ReadText());
|
||||||
Assert.AreEqual(Group_1, RunningApp.WaitForElement(q => q.Marked(lblGroup))[0].Text);
|
Assert.AreEqual(Group_1, RunningApp.WaitForElement(q => q.Marked(lblGroup))[0].ReadText());
|
||||||
|
|
||||||
RunningApp.Tap(q => q.Marked(B));
|
RunningApp.Tap(q => q.Marked(B));
|
||||||
|
|
||||||
Assert.AreEqual(B, RunningApp.WaitForElement(q => q.Marked(lblItem))[0].Text);
|
Assert.AreEqual(B, RunningApp.WaitForElement(q => q.Marked(lblItem))[0].ReadText());
|
||||||
Assert.AreEqual(Group_1, RunningApp.WaitForElement(q => q.Marked(lblGroup))[0].Text);
|
Assert.AreEqual(Group_1, RunningApp.WaitForElement(q => q.Marked(lblGroup))[0].ReadText());
|
||||||
|
|
||||||
RunningApp.Tap(q => q.Marked(C));
|
RunningApp.Tap(q => q.Marked(C));
|
||||||
|
|
||||||
Assert.AreEqual(C, RunningApp.WaitForElement(q => q.Marked(lblItem))[0].Text);
|
Assert.AreEqual(C, RunningApp.WaitForElement(q => q.Marked(lblItem))[0].ReadText());
|
||||||
Assert.AreEqual(Group_2, RunningApp.WaitForElement(q => q.Marked(lblGroup))[0].Text);
|
Assert.AreEqual(Group_2, RunningApp.WaitForElement(q => q.Marked(lblGroup))[0].ReadText());
|
||||||
|
|
||||||
RunningApp.Tap(q => q.Marked(D));
|
RunningApp.Tap(q => q.Marked(D));
|
||||||
|
|
||||||
Assert.AreEqual(D, RunningApp.WaitForElement(q => q.Marked(lblItem))[0].Text);
|
Assert.AreEqual(D, RunningApp.WaitForElement(q => q.Marked(lblItem))[0].ReadText());
|
||||||
Assert.AreEqual(Group_2, RunningApp.WaitForElement(q => q.Marked(lblGroup))[0].Text);
|
Assert.AreEqual(Group_2, RunningApp.WaitForElement(q => q.Marked(lblGroup))[0].ReadText());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,32 +8,49 @@ using System.Threading.Tasks;
|
||||||
using Xamarin.Forms.CustomAttributes;
|
using Xamarin.Forms.CustomAttributes;
|
||||||
using Xamarin.Forms.Internals;
|
using Xamarin.Forms.Internals;
|
||||||
|
|
||||||
namespace Xamarin.Forms.Controls
|
#if UITEST
|
||||||
|
using Xamarin.UITest;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using Xamarin.Forms.Core.UITests;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Xamarin.Forms.Controls.Issues
|
||||||
{
|
{
|
||||||
[Preserve (AllMembers=true)]
|
[Preserve(AllMembers = true)]
|
||||||
[Issue (IssueTracker.Github, 1875, "NSRangeException adding items through ItemAppearing", PlatformAffected.iOS)]
|
[Issue(IssueTracker.Github, 1875, "NSRangeException adding items through ItemAppearing", PlatformAffected.iOS)]
|
||||||
|
#if UITEST
|
||||||
|
[NUnit.Framework.Category(UITestCategories.ListView)]
|
||||||
|
#endif
|
||||||
public class Issue1875
|
public class Issue1875
|
||||||
: ContentPage
|
: TestContentPage
|
||||||
{
|
{
|
||||||
public Issue1875()
|
MainViewModel _viewModel;
|
||||||
|
int _start = 0;
|
||||||
|
const int NumberOfRecords = 15;
|
||||||
|
|
||||||
|
|
||||||
|
protected override void Init()
|
||||||
{
|
{
|
||||||
Button loadData = new Button { Text = "Load", HorizontalOptions = LayoutOptions.FillAndExpand };
|
Button loadData = new Button { Text = "Load", HorizontalOptions = LayoutOptions.FillAndExpand };
|
||||||
ListView mainList = new ListView {
|
ListView mainList = new ListView
|
||||||
|
{
|
||||||
VerticalOptions = LayoutOptions.FillAndExpand,
|
VerticalOptions = LayoutOptions.FillAndExpand,
|
||||||
HorizontalOptions = LayoutOptions.FillAndExpand
|
HorizontalOptions = LayoutOptions.FillAndExpand
|
||||||
};
|
};
|
||||||
|
|
||||||
mainList.SetBinding (ListView.ItemsSourceProperty, "Items");
|
mainList.SetBinding(ListView.ItemsSourceProperty, "Items");
|
||||||
|
|
||||||
_viewModel = new MainViewModel ();
|
_viewModel = new MainViewModel();
|
||||||
BindingContext = _viewModel;
|
BindingContext = _viewModel;
|
||||||
loadData.Clicked += async (sender, e) => {
|
loadData.Clicked += async (sender, e) =>
|
||||||
await LoadData ();
|
{
|
||||||
|
await LoadData();
|
||||||
};
|
};
|
||||||
|
|
||||||
mainList.ItemAppearing += OnItemAppearing;
|
mainList.ItemAppearing += OnItemAppearing;
|
||||||
|
|
||||||
Content = new StackLayout {
|
Content = new StackLayout
|
||||||
|
{
|
||||||
Children = {
|
Children = {
|
||||||
loadData,
|
loadData,
|
||||||
mainList
|
mainList
|
||||||
|
@ -41,10 +58,6 @@ namespace Xamarin.Forms.Controls
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly MainViewModel _viewModel;
|
|
||||||
int _start = 0;
|
|
||||||
const int NumberOfRecords = 15;
|
|
||||||
|
|
||||||
async void OnItemAppearing(object sender, ItemVisibilityEventArgs e)
|
async void OnItemAppearing(object sender, ItemVisibilityEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.Item == null)
|
if (e.Item == null)
|
||||||
|
@ -54,9 +67,9 @@ namespace Xamarin.Forms.Controls
|
||||||
await LoadData();
|
await LoadData();
|
||||||
}
|
}
|
||||||
|
|
||||||
async Task LoadData ()
|
async Task LoadData()
|
||||||
{
|
{
|
||||||
await _viewModel.LoadData (_start, NumberOfRecords);
|
await _viewModel.LoadData(_start, NumberOfRecords);
|
||||||
_start = _start + NumberOfRecords;
|
_start = _start + NumberOfRecords;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,47 +77,64 @@ namespace Xamarin.Forms.Controls
|
||||||
{
|
{
|
||||||
public event PropertyChangedEventHandler PropertyChanged;
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
|
||||||
public MainViewModel ()
|
public MainViewModel()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
ObservableCollection<int> _items;
|
ObservableCollection<int> _items;
|
||||||
public ObservableCollection<int> Items {
|
public ObservableCollection<int> Items
|
||||||
get {
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
if (_items == null)
|
if (_items == null)
|
||||||
_items = new ObservableCollection<int> ();
|
_items = new ObservableCollection<int>();
|
||||||
|
|
||||||
return _items;
|
return _items;
|
||||||
}
|
}
|
||||||
set {
|
set
|
||||||
|
{
|
||||||
_items = value;
|
_items = value;
|
||||||
PropertyChanged (this, new PropertyChangedEventArgs ("Items"));
|
PropertyChanged(this, new PropertyChangedEventArgs("Items"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _isLoading;
|
bool _isLoading;
|
||||||
public bool IsLoading {
|
public bool IsLoading
|
||||||
get {
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
return _isLoading;
|
return _isLoading;
|
||||||
}
|
}
|
||||||
set {
|
set
|
||||||
if (_isLoading != value) {
|
{
|
||||||
|
if (_isLoading != value)
|
||||||
|
{
|
||||||
_isLoading = value;
|
_isLoading = value;
|
||||||
PropertyChanged (this, new PropertyChangedEventArgs ("IsLoading"));
|
PropertyChanged(this, new PropertyChangedEventArgs("IsLoading"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma warning disable 1998 // considered for removal
|
#pragma warning disable 1998 // considered for removal
|
||||||
public async Task LoadData (int start, int numberOfRecords)
|
public async Task LoadData(int start, int numberOfRecords)
|
||||||
#pragma warning restore 1998
|
#pragma warning restore 1998
|
||||||
{
|
{
|
||||||
IsLoading = true;
|
IsLoading = true;
|
||||||
for (int counter = 0; counter < numberOfRecords; counter++)
|
for (int counter = 0; counter < numberOfRecords; counter++)
|
||||||
Items.Add (start + counter);
|
Items.Add(start + counter);
|
||||||
|
|
||||||
IsLoading = false;
|
IsLoading = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if UITEST
|
||||||
|
[Test]
|
||||||
|
public void NSRangeException()
|
||||||
|
{
|
||||||
|
RunningApp.WaitForElement(q => q.Marked("Load"));
|
||||||
|
RunningApp.Tap(q => q.Marked("Load"));
|
||||||
|
RunningApp.WaitForElement(q => q.Marked("5"));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -9,6 +9,7 @@ using Xamarin.Forms.Internals;
|
||||||
#if UITEST
|
#if UITEST
|
||||||
using Xamarin.UITest;
|
using Xamarin.UITest;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using Xamarin.Forms.Core.UITests;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace Xamarin.Forms.Controls.Issues
|
namespace Xamarin.Forms.Controls.Issues
|
||||||
|
@ -16,6 +17,9 @@ namespace Xamarin.Forms.Controls.Issues
|
||||||
[Preserve(AllMembers = true)]
|
[Preserve(AllMembers = true)]
|
||||||
[Issue(IssueTracker.Github, 1975, "[iOS] ListView throws NRE when grouping enabled and data changed",
|
[Issue(IssueTracker.Github, 1975, "[iOS] ListView throws NRE when grouping enabled and data changed",
|
||||||
PlatformAffected.iOS)]
|
PlatformAffected.iOS)]
|
||||||
|
#if UITEST
|
||||||
|
[NUnit.Framework.Category(UITestCategories.ListView)]
|
||||||
|
#endif
|
||||||
public class Issue1975 : TestNavigationPage
|
public class Issue1975 : TestNavigationPage
|
||||||
{
|
{
|
||||||
protected override void Init()
|
protected override void Init()
|
||||||
|
@ -37,7 +41,7 @@ namespace Xamarin.Forms.Controls.Issues
|
||||||
lv.SetBinding(ListView.ItemsSourceProperty, new Binding("Items"));
|
lv.SetBinding(ListView.ItemsSourceProperty, new Binding("Items"));
|
||||||
lv.IsGroupingEnabled = true;
|
lv.IsGroupingEnabled = true;
|
||||||
lv.GroupDisplayBinding = new Binding("Description");
|
lv.GroupDisplayBinding = new Binding("Description");
|
||||||
lv.GroupShortNameBinding= new Binding("ShortName");
|
lv.GroupShortNameBinding = new Binding("ShortName");
|
||||||
|
|
||||||
lv.ItemTemplate = new DataTemplate(() =>
|
lv.ItemTemplate = new DataTemplate(() =>
|
||||||
{
|
{
|
||||||
|
@ -49,16 +53,16 @@ namespace Xamarin.Forms.Controls.Issues
|
||||||
var layout = new StackLayout();
|
var layout = new StackLayout();
|
||||||
layout.Children.Add(button);
|
layout.Children.Add(button);
|
||||||
layout.Children.Add(lv);
|
layout.Children.Add(lv);
|
||||||
|
|
||||||
return new ContentPage { Content = layout, BindingContext = DataSample.Instance };
|
return new ContentPage { Content = layout, BindingContext = DataSample.Instance };
|
||||||
}
|
}
|
||||||
|
|
||||||
ContentPage ModifyDataPage()
|
ContentPage ModifyDataPage()
|
||||||
{
|
{
|
||||||
var contentPage = new ContentPage { Content = new Label { Text = Success, Margin = 100} };
|
var contentPage = new ContentPage { Content = new Label { Text = Success, Margin = 100 } };
|
||||||
|
|
||||||
contentPage.Appearing += (sender, args) =>
|
contentPage.Appearing += (sender, args) =>
|
||||||
DataSample.Instance.Items.Add(new Item("C"){new SubItem("Cherry"), new SubItem("Cranberry")});
|
DataSample.Instance.Items.Add(new Item("C") { new SubItem("Cherry"), new SubItem("Cranberry") });
|
||||||
|
|
||||||
return contentPage;
|
return contentPage;
|
||||||
}
|
}
|
||||||
|
@ -137,7 +141,7 @@ namespace Xamarin.Forms.Controls.Issues
|
||||||
|
|
||||||
#if UITEST
|
#if UITEST
|
||||||
[Test]
|
[Test]
|
||||||
public void UpdatingSourceOfDisposedListViewDoesNotCrash ()
|
public void UpdatingSourceOfDisposedListViewDoesNotCrash()
|
||||||
{
|
{
|
||||||
RunningApp.Tap(Go);
|
RunningApp.Tap(Go);
|
||||||
RunningApp.WaitForElement(Success);
|
RunningApp.WaitForElement(Success);
|
||||||
|
|
|
@ -15,7 +15,7 @@ namespace Xamarin.Forms.Controls.Issues
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
[Preserve(AllMembers = true)]
|
[Preserve(AllMembers = true)]
|
||||||
[Issue(IssueTracker.Github, 2929, "[UWP] ListView with null ItemsSource crashes on 3.0.0.530893",
|
[Issue(IssueTracker.Github, 2929, "[UWP] ListView with null ItemsSource crashes on 3.0.0.530893",
|
||||||
PlatformAffected.UWP)]
|
PlatformAffected.UWP)]
|
||||||
public class Issue2929 : TestContentPage
|
public class Issue2929 : TestContentPage
|
||||||
{
|
{
|
||||||
|
@ -53,7 +53,7 @@ namespace Xamarin.Forms.Controls.Issues
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
[Preserve(AllMembers = true)]
|
[Preserve(AllMembers = true)]
|
||||||
[Issue(IssueTracker.None, 99, "Make sure setting ItemSource to null doesn't blow up",
|
[Issue(IssueTracker.None, 99, "Make sure setting ItemSource to null doesn't blow up",
|
||||||
PlatformAffected.UWP)]
|
PlatformAffected.UWP)]
|
||||||
public class SetListViewItemSourceToNull : TestContentPage
|
public class SetListViewItemSourceToNull : TestContentPage
|
||||||
{
|
{
|
||||||
|
@ -100,6 +100,7 @@ namespace Xamarin.Forms.Controls.Issues
|
||||||
|
|
||||||
#if UITEST
|
#if UITEST
|
||||||
[Test]
|
[Test]
|
||||||
|
[NUnit.Framework.Category(UITestCategories.ListView)]
|
||||||
public void SettingItemsSourceToNullDoesNotCrash()
|
public void SettingItemsSourceToNullDoesNotCrash()
|
||||||
{
|
{
|
||||||
RunningApp.WaitForElement(Go);
|
RunningApp.WaitForElement(Go);
|
||||||
|
|
|
@ -0,0 +1,216 @@
|
||||||
|
using System;
|
||||||
|
using Xamarin.Forms.CustomAttributes;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using Xamarin.Forms.Internals;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
|
#if UITEST
|
||||||
|
using Xamarin.UITest;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using Xamarin.Forms.Core.UITests;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Xamarin.Forms.Controls.Issues
|
||||||
|
{
|
||||||
|
[Preserve(AllMembers = true)]
|
||||||
|
[Issue(IssueTracker.Github, 3008, "Setting ListView.ItemSource to null doesn't cause it clear out its contents", PlatformAffected.UWP)]
|
||||||
|
#if UITEST
|
||||||
|
[NUnit.Framework.Category(UITestCategories.ListView)]
|
||||||
|
#endif
|
||||||
|
public class Issue3008 : TestContentPage
|
||||||
|
{
|
||||||
|
ListView _listView;
|
||||||
|
ListView _listViewIsGrouped;
|
||||||
|
const string success1 = "InitialLoad: you should see a grouped and not grouped list view";
|
||||||
|
const string successEmpty1 = "Source is set to null: you should see nothing";
|
||||||
|
const string success2 = "Reload1: you should see a grouped and not grouped list view";
|
||||||
|
const string successEmpty2 = "If you see nothing now test has passed";
|
||||||
|
const string successEmpty3 = "List loaded and ItemSource not set: you should see nothing";
|
||||||
|
|
||||||
|
|
||||||
|
[Preserve(AllMembers = true)]
|
||||||
|
class MyHeaderViewCell : ViewCell
|
||||||
|
{
|
||||||
|
public MyHeaderViewCell()
|
||||||
|
{
|
||||||
|
Height = 25;
|
||||||
|
var label = new Label { VerticalOptions = LayoutOptions.Center };
|
||||||
|
label.SetBinding(Label.TextProperty, nameof(GroupedItem.Name));
|
||||||
|
View = label;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Preserve(AllMembers = true)]
|
||||||
|
class GroupedItem : List<Item>
|
||||||
|
{
|
||||||
|
public GroupedItem()
|
||||||
|
{
|
||||||
|
AddRange(Enumerable.Range(0, 3).Select(i => new Item()));
|
||||||
|
}
|
||||||
|
public string Name { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Preserve(AllMembers = true)]
|
||||||
|
class Item
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadData()
|
||||||
|
{
|
||||||
|
_listViewIsGrouped.ItemsSource = new ObservableCollection<GroupedItem>(Enumerable.Range(0, 3).Select(x => new GroupedItem() { Name = $"Group {x}" }));
|
||||||
|
_listView.ItemsSource = new ObservableCollection<Item>(Enumerable.Range(0, 13).Select(x => new Item()));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReloadListViews()
|
||||||
|
{
|
||||||
|
StackLayout content = Content as StackLayout;
|
||||||
|
|
||||||
|
if (_listView != null)
|
||||||
|
{
|
||||||
|
content.Children.Remove(_listView);
|
||||||
|
content.Children.Remove(_listViewIsGrouped);
|
||||||
|
}
|
||||||
|
_listView = new ListView
|
||||||
|
{
|
||||||
|
ItemTemplate = new DataTemplate(() =>
|
||||||
|
{
|
||||||
|
Label nameLabel = new Label() { Text = "Not Grouped Item" };
|
||||||
|
var cell = new ViewCell
|
||||||
|
{
|
||||||
|
View = nameLabel,
|
||||||
|
};
|
||||||
|
return cell;
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
_listViewIsGrouped = new ListView
|
||||||
|
{
|
||||||
|
IsGroupingEnabled = true,
|
||||||
|
GroupHeaderTemplate = new DataTemplate(typeof(MyHeaderViewCell)),
|
||||||
|
ItemTemplate = new DataTemplate(() =>
|
||||||
|
{
|
||||||
|
Label nameLabel = new Label() { Text = "Grouped Item" };
|
||||||
|
var cell = new ViewCell
|
||||||
|
{
|
||||||
|
View = nameLabel,
|
||||||
|
};
|
||||||
|
return cell;
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
content.Children.Add(_listView);
|
||||||
|
content.Children.Add(_listViewIsGrouped);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Init()
|
||||||
|
{
|
||||||
|
Label label = new Label();
|
||||||
|
|
||||||
|
int clickCount = 0;
|
||||||
|
Content = new StackLayout
|
||||||
|
{
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
label,
|
||||||
|
new Button()
|
||||||
|
{
|
||||||
|
Text = "Click Until Success",
|
||||||
|
Command = new Command(() =>
|
||||||
|
{
|
||||||
|
if(clickCount == 0)
|
||||||
|
{
|
||||||
|
LoadData();
|
||||||
|
label.Text = success1;
|
||||||
|
}
|
||||||
|
else if(clickCount == 1)
|
||||||
|
{
|
||||||
|
ReloadListViews();
|
||||||
|
LoadData();
|
||||||
|
label.Text = success1;
|
||||||
|
}
|
||||||
|
else if(clickCount <= 3)
|
||||||
|
{
|
||||||
|
if(_listViewIsGrouped.ItemsSource != null)
|
||||||
|
{
|
||||||
|
_listViewIsGrouped.ItemsSource = null;
|
||||||
|
_listView.ItemsSource = null;
|
||||||
|
label.Text = successEmpty1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LoadData();
|
||||||
|
label.Text = success2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(clickCount <= 5)
|
||||||
|
{
|
||||||
|
if(_listViewIsGrouped.ItemsSource != null)
|
||||||
|
{
|
||||||
|
ReloadListViews();
|
||||||
|
label.Text = successEmpty3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LoadData();
|
||||||
|
label.Text = success2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(_listViewIsGrouped.ItemsSource != null)
|
||||||
|
{
|
||||||
|
_listViewIsGrouped.ItemsSource = new List<GroupedItem>();
|
||||||
|
_listView.ItemsSource = new List<Item>();
|
||||||
|
label.Text = successEmpty2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clickCount++;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
ReloadListViews();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if UITEST && !__ANDROID__
|
||||||
|
[Test]
|
||||||
|
public void EnsureListViewEmptiesOut()
|
||||||
|
{
|
||||||
|
RunningApp.Tap("Click Until Success");
|
||||||
|
RunningApp.WaitForElement("Not Grouped Item");
|
||||||
|
RunningApp.WaitForElement("Grouped Item");
|
||||||
|
|
||||||
|
RunningApp.Tap("Click Until Success");
|
||||||
|
RunningApp.WaitForElement("Not Grouped Item");
|
||||||
|
RunningApp.WaitForElement("Grouped Item");
|
||||||
|
|
||||||
|
RunningApp.Tap("Click Until Success");
|
||||||
|
RunningApp.WaitForNoElement("Not Grouped Item");
|
||||||
|
RunningApp.WaitForNoElement("Grouped Item");
|
||||||
|
|
||||||
|
RunningApp.Tap("Click Until Success");
|
||||||
|
RunningApp.WaitForElement("Not Grouped Item");
|
||||||
|
RunningApp.WaitForElement("Grouped Item");
|
||||||
|
|
||||||
|
RunningApp.Tap("Click Until Success");
|
||||||
|
RunningApp.WaitForNoElement("Not Grouped Item");
|
||||||
|
RunningApp.WaitForNoElement("Grouped Item");
|
||||||
|
|
||||||
|
RunningApp.Tap("Click Until Success");
|
||||||
|
RunningApp.WaitForElement("Not Grouped Item");
|
||||||
|
RunningApp.WaitForElement("Grouped Item");
|
||||||
|
|
||||||
|
RunningApp.Tap("Click Until Success");
|
||||||
|
RunningApp.WaitForNoElement("Not Grouped Item");
|
||||||
|
RunningApp.WaitForNoElement("Grouped Item");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,160 @@
|
||||||
|
using System;
|
||||||
|
using Xamarin.Forms.CustomAttributes;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using Xamarin.Forms.Internals;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
|
#if UITEST
|
||||||
|
using Xamarin.UITest;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using Xamarin.Forms.Core.UITests;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Xamarin.Forms.Controls.Issues
|
||||||
|
{
|
||||||
|
[Preserve(AllMembers = true)]
|
||||||
|
[Issue(IssueTracker.Github, 3019, "Grouped ListView Header empty for adding items", PlatformAffected.UWP)]
|
||||||
|
#if UITEST
|
||||||
|
[Category(UITestCategories.ListView)]
|
||||||
|
#endif
|
||||||
|
public class Issue3019 : TestContentPage
|
||||||
|
{
|
||||||
|
ListView _listViewIsGrouped;
|
||||||
|
|
||||||
|
|
||||||
|
[Preserve(AllMembers = true)]
|
||||||
|
class MyHeaderViewCell : ViewCell
|
||||||
|
{
|
||||||
|
public MyHeaderViewCell()
|
||||||
|
{
|
||||||
|
Height = 25;
|
||||||
|
var label = new Label { VerticalOptions = LayoutOptions.Center };
|
||||||
|
label.SetBinding(Label.TextProperty, nameof(GroupedItem.Name));
|
||||||
|
View = new StackLayout()
|
||||||
|
{
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
label
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Preserve(AllMembers = true)]
|
||||||
|
class Item
|
||||||
|
{
|
||||||
|
static int counter = 0;
|
||||||
|
public Item()
|
||||||
|
{
|
||||||
|
Text = $"Grouped Item: {counter++}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Text { get; }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[Preserve(AllMembers = true)]
|
||||||
|
class GroupedItem : List<Item>
|
||||||
|
{
|
||||||
|
public GroupedItem()
|
||||||
|
{
|
||||||
|
AddRange(Enumerable.Range(0, 1).Select(i => new Item()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void LoadData()
|
||||||
|
{
|
||||||
|
_listViewIsGrouped.ItemsSource = new ObservableCollection<GroupedItem>(Enumerable.Range(0, 1).Select(x => new GroupedItem() { Name = $"Group {x}" }));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AddData()
|
||||||
|
{
|
||||||
|
var list = _listViewIsGrouped.ItemsSource as IList<GroupedItem>;
|
||||||
|
list.Add(new GroupedItem() { Name = $"Group {list.Count}" });
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReloadListViews()
|
||||||
|
{
|
||||||
|
StackLayout content = Content as StackLayout;
|
||||||
|
|
||||||
|
if (_listViewIsGrouped != null)
|
||||||
|
{
|
||||||
|
content.Children.Remove(_listViewIsGrouped);
|
||||||
|
}
|
||||||
|
|
||||||
|
_listViewIsGrouped = new ListView
|
||||||
|
{
|
||||||
|
IsGroupingEnabled = true,
|
||||||
|
GroupHeaderTemplate = new DataTemplate(typeof(MyHeaderViewCell)),
|
||||||
|
ItemTemplate = new DataTemplate(() =>
|
||||||
|
{
|
||||||
|
Label nameLabel = new Label();
|
||||||
|
nameLabel.SetBinding(Label.TextProperty, "Text");
|
||||||
|
var cell = new ViewCell
|
||||||
|
{
|
||||||
|
View = nameLabel,
|
||||||
|
};
|
||||||
|
return cell;
|
||||||
|
}),
|
||||||
|
ItemsSource = new ObservableCollection<GroupedItem>()
|
||||||
|
};
|
||||||
|
|
||||||
|
content.Children.Add(_listViewIsGrouped);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnAppearing()
|
||||||
|
{
|
||||||
|
base.OnAppearing();
|
||||||
|
AddData();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Init()
|
||||||
|
{
|
||||||
|
Label label = new Label() { Text = "If you see two group headers and can click on each row without crashing test has passed" };
|
||||||
|
|
||||||
|
Content = new StackLayout
|
||||||
|
{
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
label,
|
||||||
|
new Button()
|
||||||
|
{
|
||||||
|
Text = "Click to add more rows",
|
||||||
|
Command = new Command(() =>
|
||||||
|
{
|
||||||
|
AddData();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
ReloadListViews();
|
||||||
|
LoadData();
|
||||||
|
|
||||||
|
_listViewIsGrouped.ItemSelected += (sender, args) =>
|
||||||
|
{
|
||||||
|
label.Text = (args.SelectedItem as Item).Text + " Clicked";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#if UITEST
|
||||||
|
[Test]
|
||||||
|
public void MakeSureListGroupShowsUpAndItemsAreClickable()
|
||||||
|
{
|
||||||
|
RunningApp.WaitForElement("Group 1");
|
||||||
|
|
||||||
|
RunningApp.Tap(x => x.Marked("Grouped Item: 0"));
|
||||||
|
RunningApp.Tap(x => x.Marked("Grouped Item: 1"));
|
||||||
|
RunningApp.Tap(x => x.Marked("Grouped Item: 1 Clicked"));
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -239,6 +239,7 @@
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla59580.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla59580.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)GitHub1878.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)GitHub1878.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)Helpers\ISampleNativeControl.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)Helpers\ISampleNativeControl.cs" />
|
||||||
|
<Compile Include="$(MSBuildThisFileDirectory)Helpers\UITestHelper.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)Helpers\ViewHelper.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)Helpers\ViewHelper.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)Issue1396.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)Issue1396.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)Issue1415.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)Issue1415.cs" />
|
||||||
|
@ -319,6 +320,8 @@
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla32462.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla32462.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla36681.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla36681.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla36479.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla36479.cs" />
|
||||||
|
<Compile Include="$(MSBuildThisFileDirectory)Issue3008.cs" />
|
||||||
|
<Compile Include="$(MSBuildThisFileDirectory)Issue3019.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)MapsModalCrash.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)MapsModalCrash.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)ModalActivityIndicatorTest.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)ModalActivityIndicatorTest.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla37625.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla37625.cs" />
|
||||||
|
|
|
@ -83,14 +83,16 @@ namespace Xamarin.Forms.Platform.UWP
|
||||||
|
|
||||||
void ReloadData()
|
void ReloadData()
|
||||||
{
|
{
|
||||||
if (Element?.ItemsSource == null)
|
if (Element?.ItemsSource == null && _context != null)
|
||||||
{
|
_context.Source = null;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var allSourceItems = new ObservableCollection<object>();
|
var allSourceItems = new ObservableCollection<object>();
|
||||||
foreach (var item in Element.ItemsSource)
|
|
||||||
allSourceItems.Add(item);
|
if (Element?.ItemsSource != null)
|
||||||
|
{
|
||||||
|
foreach (var item in Element.ItemsSource)
|
||||||
|
allSourceItems.Add(item);
|
||||||
|
}
|
||||||
|
|
||||||
// WinRT throws an exception if you set ItemsSource directly to a CVS, so bind it.
|
// WinRT throws an exception if you set ItemsSource directly to a CVS, so bind it.
|
||||||
List.DataContext = _context = new CollectionViewSource
|
List.DataContext = _context = new CollectionViewSource
|
||||||
|
@ -108,11 +110,24 @@ namespace Xamarin.Forms.Platform.UWP
|
||||||
if (e.NewStartingIndex < 0)
|
if (e.NewStartingIndex < 0)
|
||||||
goto case NotifyCollectionChangedAction.Reset;
|
goto case NotifyCollectionChangedAction.Reset;
|
||||||
|
|
||||||
for (int i = e.NewItems.Count - 1; i >= 0; i--)
|
// if a NewStartingIndex that's too high is passed in just add the items.
|
||||||
SourceItems.Insert(e.NewStartingIndex, e.NewItems[i]);
|
// I realize this is enforcing bad behavior but prior to this synchronization
|
||||||
|
// code being added it wouldn't cause the app to crash whereas now it does
|
||||||
|
// so this code accounts for that in order to ensure smooth sailing for the user
|
||||||
|
if (e.NewStartingIndex >= SourceItems.Count)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < e.NewItems.Count; i++)
|
||||||
|
SourceItems.Add((e.NewItems[i] as BindableObject).BindingContext);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = e.NewItems.Count - 1; i >= 0; i--)
|
||||||
|
SourceItems.Insert(e.NewStartingIndex, (e.NewItems[i] as BindableObject).BindingContext);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case NotifyCollectionChangedAction.Remove:
|
case NotifyCollectionChangedAction.Remove:
|
||||||
foreach (var item in e.OldItems)
|
for (int i = e.OldItems.Count - 1; i >= 0; i--)
|
||||||
SourceItems.RemoveAt(e.OldStartingIndex);
|
SourceItems.RemoveAt(e.OldStartingIndex);
|
||||||
break;
|
break;
|
||||||
case NotifyCollectionChangedAction.Move:
|
case NotifyCollectionChangedAction.Move:
|
||||||
|
@ -133,6 +148,7 @@ namespace Xamarin.Forms.Platform.UWP
|
||||||
case NotifyCollectionChangedAction.Replace:
|
case NotifyCollectionChangedAction.Replace:
|
||||||
case NotifyCollectionChangedAction.Reset:
|
case NotifyCollectionChangedAction.Reset:
|
||||||
default:
|
default:
|
||||||
|
ClearSizeEstimate();
|
||||||
ReloadData();
|
ReloadData();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -168,11 +184,6 @@ namespace Xamarin.Forms.Platform.UWP
|
||||||
{
|
{
|
||||||
ClearSizeEstimate();
|
ClearSizeEstimate();
|
||||||
}
|
}
|
||||||
else if (e.PropertyName == ListView.ItemsSourceProperty.PropertyName)
|
|
||||||
{
|
|
||||||
ClearSizeEstimate();
|
|
||||||
ReloadData();
|
|
||||||
}
|
|
||||||
else if (e.PropertyName == Specifics.SelectionModeProperty.PropertyName)
|
else if (e.PropertyName == Specifics.SelectionModeProperty.PropertyName)
|
||||||
{
|
{
|
||||||
UpdateSelectionMode();
|
UpdateSelectionMode();
|
||||||
|
@ -274,14 +285,10 @@ namespace Xamarin.Forms.Platform.UWP
|
||||||
|
|
||||||
void UpdateGrouping()
|
void UpdateGrouping()
|
||||||
{
|
{
|
||||||
if (Element?.ItemsSource == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool grouping = Element.IsGroupingEnabled;
|
bool grouping = Element.IsGroupingEnabled;
|
||||||
|
|
||||||
((CollectionViewSource)List.DataContext).IsSourceGrouped = grouping;
|
if (_context != null)
|
||||||
|
_context.IsSourceGrouped = grouping;
|
||||||
|
|
||||||
var templatedItems = TemplatedItemsView.TemplatedItems;
|
var templatedItems = TemplatedItemsView.TemplatedItems;
|
||||||
if (grouping && templatedItems.ShortNames != null)
|
if (grouping && templatedItems.ShortNames != null)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче