summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla27642.cs
blob: 71acf6257adcf3149448b136f39864d65344cbfc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
using System;

using Xamarin.Forms.CustomAttributes;
using System.Text;

#if UITEST
using Xamarin.UITest;
using NUnit.Framework;
#endif

namespace Xamarin.Forms.Controls
{
	[Preserve (AllMembers = true)]
	[Issue (IssueTracker.Bugzilla, 27642, "[Windows Phone] Adding a ScrollView control to a ContentView, remove it and re-add it will cause an exception on Windows Phone")]
	public class Bugzilla27642 : TestContentPage // or TestMasterDetailPage, etc ...
	{
		ContentView _mainContent;
		protected override void Init ()
		{
			var rootGrid = new Grid {
				RowDefinitions = new RowDefinitionCollection
														  {
															 new RowDefinition { Height = new GridLength(1, GridUnitType.Star) },
															 new RowDefinition { Height = new GridLength(1, GridUnitType.Auto) },
														 },
			};


			_mainContent = new ContentView { Content = new ScrollView { Content = new Label { Text = Description } } };
			rootGrid.AddChild (_mainContent, 0, 0);


			var buttons = new StackLayout { Orientation = StackOrientation.Horizontal };

			var button1A = new Button { Text = "View 1A" };
			button1A.Clicked += (sender, args) => ShowView (_view1A);
			buttons.Children.Add (button1A);

			var button1B = new Button { Text = "View 1B" };
			button1B.Clicked += (sender, args) => ShowView (_view1B);
			buttons.Children.Add (button1B);

			var button2 = new Button { Text = "View 2" };
			button2.Clicked += (sender, args) => ShowView (_view2);
			buttons.Children.Add (button2);

			rootGrid.AddChild (buttons, 0, 1);


			Content = rootGrid;
		}

		const string Description = "A view containing a ScrollView cannot be re-used (same instance, Singleton) \n\n\n"
								+ "Steps to reproduce: \n\n" + "View1a contains a ScrollView \n"
								+ "Click: View1A -> View2 -> View1A => Exception\n\n"
								+ "View1b also contains a ScrollView, but its Content (including ScrollView!) will be re-generated during activation.\n"
								+ "Click: View1B -> View2 -> View1B => Exception\n\n"
								+ "View2 doesn't contain a ScrollView and therefore can be called again without problems.\n\n"
								+ "The Error-Message-View contains a ScrollView, too but will be re-created every time.";

		readonly View1A _view1A = new View1A ();  // always same instance, simulates Singleton from IoC
		readonly View1B _view1B = new View1B ();  // -"-
		readonly View2 _view2 = new View2 ();     // -"-

		void ShowView (ExtendedContentView view)
		{
			try {
				view.Activating ();    // implemented only for View1B
				_mainContent.Content = view;
			}
			catch (Exception ex) {
				_mainContent.Content = new ErrorView (ex);
			}
		}

		[Preserve (AllMembers = true)]
		public class ExtendedContentView : ContentView
		{
			public virtual void Activating ()
			{
			}
		}
	
		[Preserve (AllMembers = true)]
		public class View1A : ExtendedContentView
		{
			public View1A ()
			{

				BackgroundColor = Color.Olive;
				var scrollView = new ScrollView ();
				var sb = new StringBuilder ();
				for (var i = 0; i < 100; i++)
					sb.Append ("View 1a with ScrollView +++ ");

#pragma warning disable 618
				var label = new Label { Text = sb.ToString (), HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center, XAlign = TextAlignment.Center, };
#pragma warning restore 618

				scrollView.Content = label;

				Content = scrollView;

			}

		}

		[Preserve (AllMembers = true)]
		public class View1B : ExtendedContentView
		{
			public View1B ()
			{
				BackgroundColor = Color.Navy;
			}

			public override void Activating ()
			{
				var scrollView = new ScrollView ();
				var sb = new StringBuilder ();
				for (var i = 0; i < 50; i++)
					sb.Append ("View 1b with ScrollView and recreation of content +++++ ");

#pragma warning disable 618
				var label = new Label { Text = sb.ToString (), HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center, XAlign = TextAlignment.Center, };
#pragma warning restore 618

				scrollView.Content = label;

				Content = scrollView;

			}
		}

		public class View2 : ExtendedContentView
		{
			public View2 ()
			{
				BackgroundColor = Color.Teal;
#pragma warning disable 618
				Content = new Label { Text = "View 2", HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center, XAlign = TextAlignment.Center, };
#pragma warning restore 618
			}
		}

		[Preserve (AllMembers = true)]
		public class ErrorView : ExtendedContentView
		{
			public ErrorView (Exception ex)
			{
				BackgroundColor = Color.Maroon;
				Content = new ScrollView { Content = new Label { Text = ex.ToString () } };
			}
		}

	}

	public static class GridExtension
	{
		public static void AddChild (this Grid grid, View view, int column, int row, int columnspan = 1, int rowspan = 1)
		{
			if (row < 0) {
				throw new ArgumentOutOfRangeException ("row");
			}
			if (column < 0) {
				throw new ArgumentOutOfRangeException ("column");
			}
			if (rowspan <= 0) {
				throw new ArgumentOutOfRangeException ("rowspan");
			}
			if (columnspan <= 0) {
				throw new ArgumentOutOfRangeException ("columnspan");
			}
			if (view == null) {
				throw new ArgumentNullException ("view");
			}

			Grid.SetRow (view, row);
			Grid.SetRowSpan (view, rowspan);
			Grid.SetColumn (view, column);
			Grid.SetColumnSpan (view, columnspan);
			grid.Children.Add (view);
		}
	}
}